|
|
1.1 root 1: fsck/Makefile 644 3 3 1224 5045007365 6404 #
2: # for Inetco : CFLAGS = -O -DHPCOHERENT
3: # for PDP-11 : CFLAGS = -O
4: # others : CFLAGS =
5: #
6:
7: DESTDIR=/interim/etc/
8: CFLAGS = -O
9: #
10: # for PDP-11 and IBM PC: LFLAGS = -i
11: # for Z8000 : LFLAGS =
12: #
13: LFLAGS = -i
14: OBJ=main.o init.o phase1.o phase1b.o phase2.o phase3.o phase4.o phase5.o\
15: phase6.o cleanup.o util.o printf.o link.o virtual.o is_fs.o
16:
17: fsck: $(OBJ)
18: $(CC) $(CFLAGS) $(LFLAGS) -o $(DESTDIR)fsck $(OBJ)
19:
20: #
21: # for IBM PC Coherent executable, use: -DNBLK=1
22: # for others, use : -DNBLK=8
23: #
24: # If you are running out of malloc space, try lowering the
25: # value of NBLK (no smaller than 1).
26: #
27:
28: util.o: util.c
29: $(CC) -c $(CFLAGS) $< -DNBLK=8
30:
31: $(OBJ): fsck.h
32: M PC: LFLAGS = -i
33: # for Z8000 : LFLAGS =
34: #
35: LFLAGS = -i
36: OBJ=main.o init.o phase1.o phase1b.o phase2.o phase3.o phase4.o phase5.o\
37: phase6.o cleanup.o util.o printf.o link.o virtual.o is_fs.o
38:
39: fsck: $(OBJ)
40: $(CC) $(CFLAGS) $(LFLAGS) -o $(DESTDIR)fsck $(OBJ)
41:
42: #
43: # for IBM PC Coherent executable, use: -DNBLK=1
44: # for others, use : -DNBLK=8
45: #
46: # If you are rfsck/RCS/ 755 3 3 0 5050254740 5304 fsck/RCS/Makefile,v 444 3 3 2644 5045006646 7303 head 1.3;
47: branch ;
48: access ;
49: symbols ;
50: locks bin:1.3;
51: comment @@;
52:
53:
54: 1.3
55: date 91.07.29.07.44.07; author bin; state Exp;
56: branches ;
57: next 1.2;
58:
59: 1.2
60: date 91.03.15.18.33.07; author bin; state Exp;
61: branches ;
62: next 1.1;
63:
64: 1.1
65: date 91.02.08.13.26.09; author bin; state Exp;
66: branches ;
67: next ;
68:
69:
70: desc
71: @initial version provided byinitial version provided by epstein
72: @
73:
74:
75: 1.3
76: log
77: @Updated by epstein for version 321.
78: @
79: text
80: @#
81: # for Inetco : CFLAGS = -O -DHPCOHERENT
82: # for PDP-11 : CFLAGS = -O
83: # others : CFLAGS =
84: #
85: CFLAGS = -O
86: #
87: # for PDP-11 and IBM PC: LFLAGS = -i
88: # for Z8000 : LFLAGS =
89: #
90: LFLAGS = -i
91: OBJ=main.o init.o phase1.o phase1b.o phase2.o phase3.o phase4.o phase5.o\
92: phase6.o cleanup.o util.o printf.o link.o virtual.o is_fs.o
93:
94: fsck: $(OBJ)
95: $(CC) $(CFLAGS) $(LFLAGS) -o fsck $(OBJ)
96:
97: #
98: # for IBM PC Coherent executable, use: -DNBLK=1
99: # for others, use : -DNBLK=8
100: #
101: # If you are running out of malloc space, try lowering the
102: # value of NBLK (no smaller than 1).
103: #
104:
105: util.o: util.c
106: $(CC) -c $(CFLAGS) util.c -DNBLK=8
107:
108: $(OBJ): fsck.h
109: @
110:
111:
112: 1.2
113: log
114: @bob h added destdir, ownership, permissions...
115: @
116: text
117: @a6 1
118: DESTDIR = /interim/etc/
119: d16 2
120: a17 4
121: $(CC) $(CFLAGS) $(LFLAGS) -o $(DESTDIR)fsck $(OBJ)
122: su root chown bin $(DESTDIR)$@@
123: su root chgrp bin $(DESTDIR)$@@
124: su root chmod 511 $(DESTDIR)$@@
125: @
126:
127:
128: 1.1
129: log
130: @Initial revision
131: @
132: text
133: @d7 1
134: d17 4
135: a20 2
136: $(CC) $(CFLAGS) $(LFLAGS) -o fsck $(OBJ)
137:
138: @
139: unning out of malloc space, try lowering the
140: # value of NBLK (no smaller than 1).
141: #
142:
143: util.o:fsck/RCS/READ_ME,v 444 3 3 1565 4754523421 6664 head 1.1;
144: access ;
145: symbols ;
146: locks ;
147: comment @@;
148:
149:
150: 1.1
151: date 91.02.08.13.26.37; author bin; state Exp;
152: branches ;
153: next ;
154:
155:
156: desc
157: @updated version provided by epstein
158: @
159:
160:
161:
162: 1.1
163: log
164: @Initial revision
165: @
166: text
167: @Ideas for improving the performance of fsck:
168:
169: (1) Utilize a different mechanism for storing the (struct direct)
170: entries throughout phase2.c, to remove implicit memory intensive
171: redundancy.
172:
173: (2) Encode the number of links per i-node count differently, in order
174: to save space taking advantage of the typical usage under Coherent.
175:
176: (3) Arrange space for the tables in a total needed way to avoid later
177: fragmentation problems affecting the memory requests for successive
178: file systems.
179:
180: (4) Devise a more clever buffering scheme for the blocks containing
181: i-nodes to understand the differences between phase1, phase2, and
182: phase4.
183: @
184: ove implicit memory intensive
185: redundancy.
186:
187: (2) Encode the number of links per i-node count differently, in order
188: to save space tfsck/RCS/cleanup.c,v 444 3 3 2652 4753557355 7452 head 1.1;
189: access ;
190: symbols ;
191: locks ;
192: comment @ * @;
193:
194:
195: 1.1
196: date 91.02.05.16.35.30; author bin; state Exp;
197: branches ;
198: next ;
199:
200:
201: desc
202: @provided by Mark Epstein
203: @
204:
205:
206:
207: 1.1
208: log
209: @Initial revision
210: @
211: text
212: @/*
213: * Cleanup functions for phases of fsck
214: */
215:
216: #include "fsck.h"
217:
218: cleanup()
219: {
220: int retval = 0;
221:
222: if (sbpfix == TRUE)
223: writesuper();
224: prtstats();
225: if (changeflg == TRUE)
226: retval = advise();
227: close(fsfd);
228: cleanV();
229: return(retval);
230: }
231:
232: writesuper()
233: {
234: register int i;
235:
236: canshort(sbp->s_isize);
237: candaddr(sbp->s_fsize);
238: canshort(sbp->s_nfree);
239: for(i=0; i<NICFREE; i++)
240: candaddr(sbp->s_free[i]);
241: canshort(sbp->s_ninode);
242: for(i=0; i<NICINOD; i++)
243: canino(sbp->s_inode[i]);
244: cantime(sbp->s_time);
245: candaddr(sbp->s_tfree);
246: canino(sbp->s_tinode);
247: canshort(sbp->s_m);
248: canshort(sbp->s_n);
249: canlong(sbp->s_unique);
250:
251: bwrite((daddr_t)SUPERI, sbp);
252: }
253:
254: prtstats()
255: {
256: if (!fflag)
257: printf("%u files ", numfiles);
258: printf("%U blocks ", fsize - isize - totfree);
259: printf("%U free\n", totfree);
260: if ( lostsize ) {
261: lostsize = (lostsize + BSIZE - 1)/BSIZE;
262: printf("Expect roughly %U missing block%s next\n", lostsize,
263: (lostsize!=1) ? "s" : "" );
264: printf("time fsck is run as a result of inodes ");
265: printf("being cleared.\n");
266: }
267: }
268:
269: advise()
270: {
271: int retval = 0;
272:
273: printf(" ***** File System %s was modified *****\n", fsname);
274: if ( mounted ) {
275: printf(" ***** BOOT Coherent (NO SYNC!) *****\n");
276: retval = 1;
277: }
278: return(retval);
279: }
280: @
281: ocks ", fsize - isize - totfree);
282: printf("%U free\n", totfree);
283: if ( lostsize ) {
284: fsck/RCS/fsck.h,v 444 3 3 14557 4771205357 6775 head 1.2;
285: access ;
286: symbols ;
287: locks bin:1.2;
288: comment @ * @;
289:
290:
291: 1.2
292: date 91.03.18.18.45.54; author bin; state Exp;
293: branches ;
294: next 1.1;
295:
296: 1.1
297: date 91.02.08.13.26.49; author bin; state Exp;
298: branches ;
299: next ;
300:
301:
302: desc
303: @updated version provided by epstein
304: @
305:
306:
307: 1.2
308: log
309: @update provided by epstein
310: @
311: text
312: @/*
313: * Header file for fsck -- File System Check Program
314: *
315: */
316:
317: #include <canon.h>
318: #include <sys/dir.h>
319: #include <sys/fblk.h>
320: #include <sys/filsys.h>
321: #include <sys/ino.h>
322: #include <sys/stat.h>
323: #include <sys/types.h>
324: #include <time.h>
325:
326: #if HPCOHERENT
327: typedef long fsize_t;
328: #endif
329:
330: /*
331: * Conditional Compilation Flags
332: */
333:
334: #define NOT_ALL_ZERO_INODE /* Dependent on whether or not an inode */
335: #ifdef ALL_ZERO_INODE /* is totally zeroed when unallocated */
336: #undef ALL_ZERO_INODE /* or simply a zero mode and zero link */
337: #endif
338:
339:
340: /*
341: * Definitions and Externs
342: */
343:
344: #define NUL 0 /* true zero ! */
345: #define NULL ((char *)0)
346:
347: #define YES 3 /* default actions */
348: #define NO 2
349: #define ASK 1
350:
351: #define NFILSYS 10 /* max number of file systems */
352: #define MAXCH 20 /* max length of filesys name */
353:
354: #define MAXBADOK 10 /* Max number of bad blocks before excessive */
355: extern int numbad; /* num bad blocks found so far this inode*/
356:
357: #define MAXDUPOK 10 /* Max number of dup blocks */
358: /* in a single inode before excessive */
359: #define DUPTBLSIZE 20 /* Max number of dup referenced blocks */
360: extern daddr_t dupblck[]; /* table of duplicate referenced blocks */
361: extern int totdups; /* number of dup blocks found so far */
362:
363: #define MAXBADFREE 10 /* max bad in free list before abort */
364: #define MAXDUPFREE 10 /* max dup in free list before abort */
365:
366: #define GOOD 1 /* returned by bad() in util.c */
367: #define BAD 0
368:
369: #define TRUE 1 /* errflag possibilities */
370: #define FALSE 0
371: extern int errflag; /* errflag indicates not to do phases */
372:
373: #define OK 1 /* used to indicate excessive bad/dup */
374: #define STOP 0 /* blocks in an inode in phase1.c */
375: #define BAD_DUP 2
376:
377: #define FIRSTIN 2 /* First real inode number */
378:
379: #define ND 10 /* Number of Direct Blocks */
380: #undef NI
381: #define NI 1
382: #define NII 1
383: #define NIII 1
384: #undef NADDR
385: #define NADDR (ND+NI+NII+NIII)
386: extern int offsets[]; /* table of offsets for level of indirection */
387: /* for the blocks in an inode */
388:
389: extern char nextchar(); /* used in util.c */
390: extern int fsfd; /* file system file descriptor */
391: extern int mdaction; /* default action for this invocation */
392: extern int daction; /* default action for current file system */
393: extern int writeflg; /* system write ok or read-only */
394: extern int qflag; /* quiet fsck flag */
395: extern int fflag; /* fast fsck flag */
396: extern int sflag; /* force free list salvation */
397: extern daddr_t fsize; /* file system size in blocks */
398: extern int isize; /* first block not in inode list */
399: /* isize is NOT unsigned so that comparisons */
400: /* with longs will not cast the long to */
401: /* unsigned thus producing confusing results */
402:
403: extern daddr_t totfree; /* running count of total free blocks */
404: extern unsigned ninodes;/* Number of inodes in the files system */
405: extern char *fsname; /* file system name */
406: extern fsize_t pinfo(); /* returns size of file, in phase2.c */
407: extern ino_t lostfound(); /* returns inumber of lost+found dir */
408: extern struct dinode *ptrino(); /* returns a ptr to inode, give number */
409: extern char databuf[]; /* buffer to read in block, used throughout */
410: extern char buf2[]; /* alternate data buffer */
411: extern daddr_t cdbn; /* current block number, used by nextblock() */
412: #define DSIZE (sizeof(struct direct))
413: extern char *lostname; /* name of lost+found directory */
414: extern char *nameit(); /* nameing function for lost dirs and files */
415: extern int depth; /* used during tree traversal in phase2.c */
416: extern struct direct *path[]; /* used during tree traversal in phase2.c */
417: extern char *typename(); /* return string to type of inode */
418: extern struct filsys *sbp; /* Super Block */
419: extern int sbpfix; /* flag for super block fixes */
420: extern struct stat stats; /* used by statit() in util.c */
421: extern dev_t rootdev; /* root device number */
422: extern dev_t fsysrdev; /* file system real device number */
423: extern int mounted; /* flag indicating mountedness of filesystem */
424: extern int changeflg; /* file system modified flag */
425: extern int fixerup; /* flag to rebuild free list */
426: extern char *fixit; /* Prompt message phase[45].c */
427: extern int numfiles; /* num files in system */
428: extern daddr_t imap(); /* function for disk block mapping in util.c */
429: extern fsize_t lostsize; /* Size of files cleared in phase4.c */
430: extern char *tmpfile; /* TMP File name for virtual.c */
431:
432: #define SUCCESS 1 /* used in connect() in phase3.c */
433: #define FAILURE 0
434:
435: #define MODEMASK 0x07
436: #define ALLOCMASK 0x06
437: #define UNALLOC 0x00
438: #define UNKNOWN 0x01
439: #define IDIR 0x02
440: #define IREG 0x03
441: #define ICHR 0x04
442: #define IBLK 0x05
443: #define IPIPE 0x06
444: #define IBAD_IDUP 0x08
445: #define VISITED 0x10
446: #define UNREFDIR 0x20
447: #define CHILDDIR 0x40
448: #define IFREELIST 0x80
449:
450: /*
451: * Macros for tables
452: */
453:
454: #define LOGNBPC 3 /* Log2 Number of Bits per Character */
455:
456: /* Actions for virtual block system */
457: enum vact { testBlock, markBlock, unmarkBlock, grabBlock,
458: testDup, markDup, unmarkDup, setDup,
459: Flags, setFlags, orFlags,
460: linkCtr, incLinkctr, setLinkctr };
461:
462: #define testblock(bn) findblock((unsigned long)(bn), testBlock)
463: #define markblock(bn) findblock((unsigned long)(bn), markBlock)
464: #define unmarkblock(bn) findblock((unsigned long)(bn), unmarkBlock)
465:
466: #define testdup(bn) findblock((unsigned long)(bn), testDup)
467: #define markdup(bn) findblock((unsigned long)(bn), markDup)
468: #define unmarkdup(bn) findblock((unsigned long)(bn), unmarkDup)
469:
470: #define flags(ino) findblock((unsigned long)(ino), Flags)
471: #define setflags(ino, data) findblock((unsigned long)(ino), setFlags, data)
472: #define orflags(ino, data) findblock((unsigned long)(ino), orFlags, data)
473:
474: #define linkctr(ino) findblock((unsigned long)(ino), linkCtr)
475: #define inclinkctr(ino) findblock((unsigned long)(ino), incLinkctr)
476: #define setlinkctr(ino, data) findblock((unsigned long)(ino), setLinkctr, data)
477:
478: #define badblks(ino) ( flags(ino)&IBAD_IDUP )
479:
480: /*
481: * Miscellany
482: */
483:
484: #define NBPC 8 /* number of bits per character */
485: #define MAXINTN 255 /* used for interleave table */
486: /* in phase6.c */
487: /*
488: * Stdio Stuff
489: */
490:
491: #define putchar(c) { char b = c; write(1, &b, 1); }
492: extern char *malloc();
493: extern char *calloc();
494:
495: @
496:
497:
498: 1.1
499: log
500: @Initial revision
501: @
502: text
503: @d85 1
504: @
505: ne inclinkctr(ino) findblock((unsigned long)(ino), incLinkctr)
506: #define setlinkctr(ino, data) findblock((unsigned long)(ino), setLinkctr, data)
507:
508: #fsck/RCS/init.c,v 444 3 3 14501 5045006666 6767 head 1.2;
509: branch ;
510: access ;
511: symbols ;
512: locks bin:1.2;
513: comment @ * @;
514:
515:
516: 1.2
517: date 91.07.29.07.44.33; author bin; state Exp;
518: branches ;
519: next 1.1;
520:
521: 1.1
522: date 91.02.05.16.36.03; author bin; state Exp;
523: branches ;
524: next ;
525:
526:
527: desc
528: @prov by epstein
529: @
530:
531:
532: 1.2
533: log
534: @Updated by epstein for version 321.
535: @
536: text
537: @/*
538: * Perform initialization for phases of fsck
539: */
540: #include "fsck.h"
541: #include <mnttab.h>
542: #include <mtab.h>
543:
544: int fsfd; /* file system file descriptor */
545: int writeflg; /* write ok or read-only flag */
546: daddr_t fsize = SUPERI+1; /* file system size in blocks */
547: /* Allows for read of Super Block */
548: int isize; /* First block not in inode list */
549: daddr_t totfree; /* Running total free block count */
550: unsigned ninodes; /* number of inodes */
551: int numfiles; /* number of files in file system */
552:
553: char superb[BSIZE]; /* Super Block */
554: struct filsys *sbp = superb;
555: int sbpfix; /* flag for super block fixes */
556:
557: int offsets[] = /* table of offsets for the levels */
558: { ND, ND+NI, ND+NI+NII, /* of indirection of blocks in the */
559: ND+NI+NII+NIII }; /* inode block list */
560:
561: daddr_t dupblck[DUPTBLSIZE]; /* duplicate referenced blocks */
562: int totdups; /* number of dup blocks so far */
563:
564: init()
565: {
566: int mode;
567: struct stat status;
568: unsigned short stmode;
569:
570: mode = (mdaction == NO) ? 0 : 2;
571:
572: if ( (fsfd = open(fsname, mode)) == (-1) ) {
573: mode = 0;
574: if ( (fsfd = open(fsname, mode)) == (-1) ) {
575: nonfatal("Can't open: %s", fsname);
576: return;
577: }
578: }
579:
580: if (mode == 0) {
581: daction = NO;
582: writeflg = FALSE;
583: } else {
584: daction = mdaction;
585: writeflg = TRUE;
586: }
587:
588: printf("%s: %s\n", fsname, (mode == 0) ? "(NO WRITE)" : "");
589:
590: if ( fstat(fsfd, &status) == (-1) ) {
591: nonfatal("Can't stat: %s", fsname);
592: return;
593: }
594:
595: stmode = status.st_mode & S_IFMT;
596: if ( (stmode != S_IFBLK) && (stmode != S_IFCHR) )
597: switch(query("file is not a block or character device; OK?")){
598: case YES:
599: break;
600: case NO:
601: errflag = TRUE;
602: return;
603: }
604:
605: domount();
606: sbpfix = FALSE;
607: readsuper();
608: checksuper();
609: if ( !errflag )
610: alloctables();
611: }
612:
613: /*
614: * Read in the super block and canonicalize
615: */
616:
617: readsuper()
618: {
619: register int i;
620:
621: bread((daddr_t)SUPERI, superb);
622: sbp = superb;
623:
624: canshort(sbp->s_isize);
625: candaddr(sbp->s_fsize);
626: canshort(sbp->s_nfree);
627: for(i=0; i<NICFREE; i++)
628: candaddr(sbp->s_free[i]);
629: canshort(sbp->s_ninode);
630: for(i=0; i<NICINOD; i++)
631: canino(sbp->s_inode[i]);
632: cantime(sbp->s_time);
633: candaddr(sbp->s_tfree);
634: canino(sbp->s_tinode);
635: canshort(sbp->s_m);
636: canshort(sbp->s_n);
637: canlong(sbp->s_unique);
638:
639: }
640:
641: /*
642: * Check super block for obvious inconsistencies
643: */
644:
645: checksuper()
646: {
647: fsize = sbp->s_fsize;
648: isize = sbp->s_isize;
649: totfree = fsize - isize;
650:
651: if ( (isize<=INODEI) || (isize>=fsize) || (fsize<=INODEI) ) {
652: badsuper("Size check: fsize %U isize %u", fsize, isize);
653: errflag = TRUE;
654: }
655:
656: if ( sbp->s_nfree > NICFREE )
657: badsuper("Too large free block count");
658:
659: if ( sbp->s_ninode > NICINOD )
660: badsuper("Too large free i-node count");
661: }
662:
663: /*
664: * Super Block Error Functions
665: */
666:
667: badsuper(x)
668: {
669: printf("%r\n", &x);
670: printf("fsck: %s: Bad Super Block: %u\n", fsname, SUPERI);
671: }
672:
673: /*
674: * Allocate the necessary buffers for tables
675: */
676:
677: alloctables()
678: {
679: unsigned num, numl;
680:
681: numl = 0;
682: if (!fflag) {
683: ninodes = (unsigned) (isize - INODEI) * INOPB;
684: numl = (unsigned) ninodes;
685: }
686:
687: num = (unsigned) ((fsize+NBPC-1)/NBPC) * sizeof(char);
688: initV(numl, numl, num, num); /* virtual allocation */
689:
690: numfiles = /* number of files in the file system */
691: totdups = 0; /* num dup blocks */
692: }
693:
694: /*
695: * domount() checks the files /etc/mnttab and /etc/mtab to find
696: * out where the file system is mounted (if at all). It then
697: * reports where (and when if possible) it was last mounted.
698: */
699: char *mnttab_name = "/etc/mnttab";
700: char *mtab_name = "/etc/mtab";
701: char *bttime_name = "/etc/boottime";
702:
703: domount()
704: {
705: int fd;
706: struct mnttab mnttab;
707: struct mtab mtab;
708: register char *name;
709: struct stat sbuf;
710: time_t boottime;
711: int nothing();
712: char devname[MNTNSIZ+6] = "/dev/";
713:
714: mounted = FALSE;
715: name = fsname; /* strip off all initial */
716: while (*name++ != '\0') ; /* directories in fsname */
717: while ( (*--name != '/') && (name>fsname) ) ;
718: if (*name == '/') name++;
719:
720: if ( stat(bttime_name, &sbuf) == -1 )
721: boottime = (time_t)0;
722: else
723: boottime = sbuf.st_mtime;
724:
725: if ( (fd=open(mnttab_name, 0)) != (-1) ) {
726: while ( read(fd, &mnttab, sizeof(mnttab))==sizeof(mnttab) )
727: if ( mnttab.mt_dev[0] && mnttab.mt_filsys[0] ) {
728: strncpy(&devname[5], mnttab.mt_filsys, MNTNSIZ);
729: devname[MNTNSIZ+5] = '\0';
730: statit(devname, nothing);
731: if (stats.st_rdev != fsysrdev)
732: continue;
733: statit(mnttab.mt_dev, nothing);
734: mounted = (stats.st_dev == fsysrdev);
735: prmnttab(&mnttab, boottime);
736: return;
737: }
738: }
739: if ( (fd=open(mtab_name, 0)) != (-1) ) {
740: while ( read(fd, &mtab, sizeof(mtab))==sizeof(mtab) )
741: if ( mtab.mt_name[0] && mtab.mt_special[0] ) {
742: strncpy(&devname[5], mtab.mt_special, MNAMSIZ);
743: devname[MNAMSIZ+5] = '\0';
744: statit(devname, nothing);
745: if (stats.st_rdev != fsysrdev)
746: continue;
747: statit(mtab.mt_name, nothing);
748: mounted = (stats.st_dev == fsysrdev);
749: prmtab(&mtab);
750: return;
751: }
752: }
753:
754: if (fsysrdev == rootdev)
755: mounted = TRUE;
756: else
757: mounted = FALSE;
758:
759: }
760:
761: prmnttab(ptr, boottime)
762: struct mnttab *ptr;
763: time_t boottime;
764: {
765: if (mounted) {
766: if (boottime < ptr->mt_time)
767: boottime = ptr->mt_time;
768: printf("%s mounted on %.*s as of %s", fsname, MNTNSIZ,
769: ptr->mt_dev, ctime(&boottime));
770: } else
771: printf("%s unmounted. Last mounted on %.*s -- %s",
772: fsname, MNTNSIZ, ptr->mt_dev,
773: ctime(&ptr->mt_time));
774: }
775:
776:
777: prmtab(ptr)
778: struct mtab *ptr;
779: {
780: if (mounted)
781: printf("%s mounted on %.*s\n", fsname, MNAMSIZ, ptr->mt_name);
782: else
783: printf("%s unmounted. Last mounted on %.*s\n", fsname,
784: MNAMSIZ, ptr->mt_name);
785: }
786:
787: nothing()
788: {}
789: @
790:
791:
792: 1.1
793: log
794: @Initial revision
795: @
796: text
797: @d176 1
798: d178 1
799: d191 11
800: a201 10
801: if (mnttab.mt_dev[0] != '\0')
802: if ( strcmp(name, mnttab.mt_filsys) == 0 ) {
803: statit(mnttab.mt_dev, nothing);
804: if (stats.st_dev == fsysrdev)
805: mounted = TRUE;
806: else
807: mounted = FALSE;
808: prmnttab(&mnttab, boottime);
809: return;
810: }
811: d205 11
812: a215 10
813: if (mtab.mt_name[0] != '\0')
814: if ( strcmp(name, mtab.mt_special) == 0 ) {
815: statit(mtab.mt_name, nothing);
816: if (stats.st_dev == fsysrdev)
817: mounted = TRUE;
818: else
819: mounted = FALSE;
820: prmtab(&mtab);
821: return;
822: }
823: @
824: mt_dev[0] != '\0')
825: if ( strcmp(name, mnttab.mt_filsys) == 0 ) {
826: statit(mnttab.mt_dev, nothing);
827: if (stats.st_dev == fsysrdev)
828: mounted = TRUE;
829: else
830: mounted = FAfsck/RCS/is_fs.c,v 444 3 3 4004 4753557413 7112 head 1.1;
831: access ;
832: symbols ;
833: locks ;
834: comment @ * @;
835:
836:
837: 1.1
838: date 91.02.05.16.36.22; author bin; state Exp;
839: branches ;
840: next ;
841:
842:
843: desc
844: @prov by epstein
845: @
846:
847:
848:
849: 1.1
850: log
851: @Initial revision
852: @
853: text
854: @#include <sys/stat.h>
855: #include <canon.h>
856: #include <sys/filsys.h>
857:
858: /*
859: * Check if a special file is a well-formed filesystem.
860: * This routine is derived from code in "mount.c".
861: * Return values:
862: * -1 Not a device, cannot open, read or seek failed
863: * 0 No filesystem
864: * 1 Legal filesystem
865: */
866: int
867: is_fs(special) char *special;
868: {
869: static struct filsys f;
870: struct stat sbuf;
871: register int fd;
872: register struct filsys *fp;
873: register daddr_t *dp;
874: register ino_t *ip, maxinode;
875:
876: if (stat(special, &sbuf) < 0)
877: return -1; /* cannot stat device */
878: else if ((sbuf.st_mode&S_IFMT) != S_IFBLK
879: && (sbuf.st_mode&S_IFMT) != S_IFCHR)
880: return -1; /* not a special file */
881: else if ((fd = open(special, 2)) < 0)
882: return -1; /* cannot open */
883: else if (lseek(fd, (long)SUPERI*BSIZE, 0) == -1L
884: || read(fd, &f, sizeof(f)) != sizeof(f)) {
885: close(fd);
886: return -1; /* seek or read failed */
887: } else
888: close(fd); /* so far so good */
889:
890: /* Canonical stuff. */
891: fp = &f;
892: canshort(fp->s_isize);
893: candaddr(fp->s_fsize);
894: canshort(fp->s_nfree);
895: for (dp = &fp->s_free[0]; dp < &fp->s_free[NICFREE]; dp += 1)
896: candaddr(*dp);
897: canshort(fp->s_ninode);
898: for (ip = &fp->s_inode[0]; ip < &fp->s_inode[NICINOD]; ip += 1)
899: canino(*ip);
900: candaddr(fp->s_tfree);
901: canino(fp->s_tinode);
902:
903: /* Test for rationality. */
904: maxinode = (fp->s_isize - INODEI) * INOPB + 1;
905: if (fp->s_isize >= fp->s_fsize)
906: return 0;
907: if ((fp->s_tfree < fp->s_nfree)
908: || (fp->s_tfree >= fp->s_fsize - fp->s_isize + 1))
909: return 0;
910: if ((fp->s_tinode < fp->s_ninode) || (fp->s_tinode >= maxinode-1 ))
911: return 0;
912: for (dp = &fp->s_free[0]; dp < &fp->s_free[fp->s_nfree]; dp += 1)
913: if ((*dp < fp->s_isize) || (*dp >= fp->s_fsize))
914: return 0;
915: for (ip = &fp->s_inode[0]; ip < &fp->s_inode[fp->s_ninode]; ip += 1)
916: if ((*ip < 1) || (*ip > maxinode))
917: return 0;
918: return 1;
919: }
920: @
921: INODEI) * INOPB + 1;
922: if (fp->s_isize >= fp->s_fsize)
923: return 0;
924: if ((fp->s_tfree < fp->s_nfree)
925: || (fp->s_tfree >= fp->s_fsize - fp->s_isize + 1))
926: return 0;
927: if ((fp->s_tinode < fp->s_ninode) || (fp->s_tinode >= maxinode-1 ))
928: return 0;
929: for (dp = &fp->s_free[0]; dp < &fp->s_free[fp->s_nfree]; dp += 1)
930: if ((*dp < fp->s_isize) || (*dp >= fp->s_fsize))
931: return 0;
932: for (ip = &fp->s_inode[0]; ip < &fp->s_inode[fp->s_ninode]; ip += 1)
933: if ((*ip < 1) || (*ip > maxinode))
934: return 0;
935: return 1;
936: fsck/RCS/link.c,v 444 3 3 3277 4753557430 6756 head 1.1;
937: access ;
938: symbols ;
939: locks ;
940: comment @ * @;
941:
942:
943: 1.1
944: date 91.02.05.16.36.34; author bin; state Exp;
945: branches ;
946: next ;
947:
948:
949: desc
950: @prov by epstein
951: @
952:
953:
954:
955: 1.1
956: log
957: @Initial revision
958: @
959: text
960: @/*
961: * Routines to handle the counting of links for each i-node
962: */
963:
964: #include "fsck.h"
965:
966: linkincr(inum)
967: ino_t inum;
968: {
969: if (inclinkctr(inum) == 0 )
970: fatal("Too many links in i-node, %d", inum);
971: }
972:
973: /*
974: * The following is the beginning of thinking of how to change
975: * the number of bits used in the link count tables from 8-per
976: * i-node to 2-per i-node, with additional tables for those
977: * i-nodes with more than 2 links. The changes would be to the
978: * definition of i_lnks, the macro linkctr(), the function linkincr(),
979: * and in init.c, the allocation of table space.
980: */
981:
982: #ifdef NEWLINKSTUFFF
983:
984: char *linkmap; /* table of inodes with one link */
985:
986: #define testlink(in) ( linkmap[((unsigned)bn)>>(LOGNBPC-1)] & \
987: 3 << (((unsigned)bn)&(NBPC>>1)) )
988: #define marklink(in) ( linkmap[((unsigned)bn)>>(LOGNBPC-1)] |= \
989: 1 << (((unsigned)bn)&(NBPC-2)) )
990: #define unmarklink(in) ( linkmap[((unsigned)bn)>>(LOGNBPC-1)] ^= \
991: 1 << (((unsigned)bn)&(NBPC-2)) )
992:
993: linkcntr(inum)
994: ino_t inum;
995: {
996: index = ((unsigned) inum) >> (LOGNBPC-1) ;
997: distance = ((unsigned) inum) & ((NBPC>>1) - 1) ;
998: mask = 3 << distance;
999: answer = ( linkmap[index] & mask ) >> distance;
1000:
1001: if ( answer < 3 )
1002: return(answer);
1003:
1004: hash = inum & 0xFF;
1005: bucket = &linktable[hash];
1006: bktinum = bucket->inumb;
1007:
1008: if ( bktinum == inum ) {
1009: answer = bucket->numlink;
1010: if ( answer == 0xFF )
1011: return( bigcntr(inum) );
1012: else
1013: return( answer + 3 );
1014: }
1015:
1016: if ( bktinum > inum )
1017: fatal("internal linktable corruption.");
1018:
1019:
1020: }
1021:
1022: linkincr(inum)
1023: ino_t inum;
1024: {
1025: }
1026:
1027: #endif
1028: @
1029: m) >> (LOGNBPC-1) ;
1030: distance = ((unsigned) inum) & ((NBPC>>1) - 1) ;
1031: mask = 3 << distance;
1032: answer = ( linkmap[index] & mask ) >> distance;
1033:
1034: if ( answer < 3 )
1035: return(answer);
1036:
1037: hash = inum & 0xFF;
1038: bucket = &linktable[hash];
1039: bktinum = bucket->inumb;
1040:
1041: if ( bktinum == inum ) {
1042: answer = bucket->numlink;
1043: if ( ansfsck/RCS/main.c,v 444 3 3 15241 5045006700 6737 head 1.3;
1044: branch ;
1045: access ;
1046: symbols ;
1047: locks bin:1.3;
1048: comment @ * @;
1049:
1050:
1051: 1.3
1052: date 91.07.29.07.44.44; author bin; state Exp;
1053: branches ;
1054: next 1.2;
1055:
1056: 1.2
1057: date 91.03.18.18.43.33; author bin; state Exp;
1058: branches ;
1059: next 1.1;
1060:
1061: 1.1
1062: date 91.02.05.16.36.45; author bin; state Exp;
1063: branches ;
1064: next ;
1065:
1066:
1067: desc
1068: @prov by epstein
1069: @
1070:
1071:
1072: 1.3
1073: log
1074: @Updated by epstein for version 321.
1075: @
1076: text
1077: @/*
1078: * fsck -- File System Check Program
1079: * an interactive file system check and repair program.
1080: *
1081: * Usage:
1082: * /etc/fsck [-y] [-n] [-q] [-f] [-{sS}] [-t TMPFILE] [filesystem ...]
1083: * audit and interactively repair inconsistent conditions for
1084: * file systems. Options -y and -n indicate an assumed response
1085: * to all questions asked by fsck. Default is to prompt operator
1086: * for yes/no response. Option -q is to quiet fsck from printing
1087: * certain messages, i.e. no size check messages, unreferenced
1088: * pipes will be silently removed, and counts in the superblock
1089: * will be automatically fixed and free list salvaged, if necessary.
1090: * Option -f is for a 'fast' check of the file system, i.e. only
1091: * check blocks, sizes, superblock counts, and the free list.
1092: * (-f) does not check pathnames, connectivity, or reference
1093: * counts. Option -s forces the reconstruction (or salvaging) of
1094: * both the free inode list and the free block list, even if there
1095: * are no file system problems. This will reorder the free block
1096: * list in the best order to limit additional fragmentation (respecting
1097: * interleaving as well). Note: Option -s will be ignored on mounted
1098: * file systems. The option -S acts in the same manner as -s except
1099: * that it will not be ignored on mounted file systems. Beware: -S
1100: * on mounted file systems should only be used if you intend to reboot
1101: * NO SYNC immediately afterwards. Option -t sets the temporary file
1102: * to use for disk caching of necessary tables on filesystems which are
1103: * too big to do in core. The temporary file defaults to "/dev/rram1",
1104: * which must be there.
1105: */
1106:
1107: #include "fsck.h"
1108:
1109: int errflag;
1110:
1111: int mdaction; /* default action for invocation */
1112: int daction; /* default action for file system */
1113: int gSflag=FALSE; /* force salvage flag ignored mounted */
1114: int gsflag=FALSE; /* force salvage flag ignored mounted */
1115: int sflag=FALSE; /* force salvage flag */
1116: int qflag=FALSE; /* fsck quiet flag */
1117: int fflag=FALSE; /* fsck fast flag */
1118:
1119: char *tmpfile = NULL; /* TMP file for virtual.c */
1120: char *checklistfile = "/etc/checklist"; /* default file for list of file */
1121: /* systems to fsck. */
1122: char *filelist[NFILSYS]; /* list of filesystems */
1123: char word[MAXCH]; /* hold single words */
1124: char *fsname; /* file system name */
1125:
1126: dev_t rootdev; /* root device number */
1127: dev_t fsysrdev; /* file system real device number */
1128: int mounted; /* flag for mounted file system */
1129:
1130: int changeflg; /* file system modified flag */
1131:
1132: main(argc, argv)
1133: char *argv[];
1134: {
1135: int yflag=0, nflag=0;
1136: int retval;
1137:
1138: while (argc>1 && *argv[1]=='-') {
1139: switch (argv[1][1]) {
1140: case 'q':
1141: qflag = TRUE;
1142: break;
1143: case 'y':
1144: yflag = 1;
1145: break;
1146: case 'n':
1147: nflag = 1;
1148: break;
1149: case 'f':
1150: fflag = TRUE;
1151: break;
1152: case 'S':
1153: gSflag = TRUE;
1154: break;
1155: case 's':
1156: gsflag = TRUE;
1157: break;
1158: case 't':
1159: tmpfile = argv[2];
1160: argc--;
1161: argv++;
1162: break;
1163: default:
1164: usage();
1165: break;
1166: }
1167:
1168: argc--;
1169: argv++;
1170: }
1171:
1172: if ( yflag+nflag > 1 )
1173: usage();
1174:
1175: mdaction = ( yflag ? YES :
1176: nflag ? NO : ASK );
1177:
1178: if ( argc > 1 )
1179: retval = allfsck(argv+1);
1180: else {
1181: getlist();
1182: retval = allfsck(filelist);
1183: }
1184: exit(retval);
1185: }
1186:
1187:
1188: /*
1189: * perform fsck on each of the individual filesystem in list
1190: */
1191:
1192: allfsck(fsl)
1193: register char **fsl;
1194: {
1195: int fatal();
1196: int retval = 0;
1197:
1198: sync();
1199: statit("/", fatal);
1200: rootdev = stats.st_dev;
1201: while (*fsl != NULL)
1202: retval |= fsck(*fsl++);
1203: return(retval);
1204: }
1205:
1206: /*
1207: * get the names of the filesystems from the default file
1208: * checklistfile (e.g. /etc/checklist)
1209: */
1210:
1211: getlist()
1212: {
1213: int fd;
1214: int index, size;
1215:
1216: if ( (fd = open(checklistfile, 0)) == (-1) )
1217: fatal("Can't open checklist file: %s", checklistfile);
1218:
1219: index = 0;
1220: while ( ((size = getword(fd)) != 0) && (index < NFILSYS) ) {
1221: filelist[index] = malloc( size );
1222: strcpy(filelist[index++], word);
1223: }
1224:
1225: if (size != 0)
1226: fatal("Too many file systems in checklist file: %s",
1227: checklistfile);
1228:
1229: filelist[index] = NULL;
1230:
1231: close(fd);
1232: }
1233:
1234: /*
1235: * read in the next "word" from file with descriptor fd
1236: * return the length of the word.
1237: */
1238:
1239: getword(fd)
1240: int fd;
1241: {
1242: int n = 0, num;
1243: char *cp = word;
1244: char ch;
1245:
1246: while ( ( (num=read(fd, &ch, 1)) == 1 ) &&
1247: ( (ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r') ) );
1248:
1249: if (num != 1)
1250: return(0);
1251:
1252: do {
1253: *cp++ = ch;
1254: } while ( (++n < MAXCH) && (read(fd, &ch, 1) == 1) &&
1255: (ch != ' ') && (ch != '\t') && (ch != '\n') && (ch != '\r') );
1256:
1257: *cp = '\0';
1258:
1259: return(n+1);
1260: }
1261:
1262: /*
1263: * perform fsck on the given filesystem
1264: */
1265: fsck(name)
1266: char *name;
1267: {
1268: int retval = 1;
1269: int nonfatal();
1270:
1271: fsname = name; /* file system name */
1272: errflag = FALSE;
1273: statit(fsname, nonfatal);
1274: fsysrdev = stats.st_rdev;
1275: if ( errflag )
1276: return(retval);
1277: changeflg = FALSE;
1278: init();
1279: if ( sflag = ((gsflag && !mounted) || gSflag) )
1280: printf("Switch \"-s\" selected to automatically rebuild free lists\n");
1281: if (!sflag && gsflag)
1282: printf("Ignoring \"-s\" on mounted file system\n");
1283: if ( !errflag ) {
1284: phase1(); /* check blocks and sizes */
1285: if ( !fflag ) {
1286: phase2(); /* check pathnames */
1287: phase3(); /* check connectivity */
1288: phase4(); /* check reference counts */
1289: }
1290: phase5(); /* check free list */
1291: phase6(); /* salvage free list */
1292: retval = cleanup();
1293: }
1294: return(retval);
1295: }
1296:
1297: usage()
1298: {
1299: printf("\
1300: Usage: /etc/fsck [-y] [-n] [-q] [-f] [-{sS}] [-t TMPFILE] [filesystem ...]\n");
1301: _exit(1);
1302: }
1303: @
1304:
1305:
1306: 1.2
1307: log
1308: @update provided by epstein
1309: @
1310: text
1311: @d6 1
1312: a6 1
1313: * /etc/fsck [-y] [-n] [-q] [-f] [-s] [-t TMPFILE] [filesystem ...]
1314: d21 7
1315: a27 3
1316: * interleaving as well). Option -t sets the temporary file to use
1317: * for disk caching of necessary tables on filesystems which are too
1318: * big to do in core. The temporary file defaults to "/dev/rram1",
1319: d37 2
1320: d76 3
1321: d80 1
1322: a80 1
1323: sflag = TRUE;
1324: d203 4
1325: d224 1
1326: a224 1
1327: Usage: /etc/fsck [-y] [-n] [-q] [-f] [-s] [-t TMPFILE] [filesystem ...]\n");
1328: @
1329:
1330:
1331: 1.1
1332: log
1333: @Initial revision
1334: @
1335: text
1336: @d6 1
1337: a6 1
1338: * /etc/fsck [-y] [-n] [-q] [-f] [-t TMPFILE] [filesystem ...]
1339: d17 8
1340: a24 4
1341: * counts. Option -t sets the temporary file to use for disk caching
1342: * of necessary tables on filesystems which are too big to do in core.
1343: * The temporary file defaults to "/dev/rram1", which must be there.
1344: *
1345: d33 3
1346: a35 2
1347: int qflag=FALSE; /* fsck quiet flag */
1348: int fflag=FALSE; /* fsck fast flag */
1349: d70 3
1350: d211 1
1351: a211 1
1352: Usage: /etc/fsck [-y] [-n] [-q] [-f] [-t TMPFILE] [filesystem ...]\n");
1353: @
1354: g
1355: @Initial revision
1356: @
1357: text
1358: @d6 1
1359: a6 1
1360: * /etc/fsck [-y] [-n] [-q] [-f] [-t TMPFILE] [filesystem ...]
1361: d17 8
1362: a24 4
1363: * counts. Option -t sets the temporary file to use for disk caching
1364: * of necessary tables on filesystems which are too big to do in core.
1365: * The temporary file defaults to "/dev/rram1", which must be there.
1366: *
1367: d33 3
1368: a35 2
1369: int qflag=FALSfsck/RCS/phase1.c,v 444 3 3 16554 4771205175 7220 head 1.2;
1370: access ;
1371: symbols ;
1372: locks bin:1.2;
1373: comment @ * @;
1374:
1375:
1376: 1.2
1377: date 91.03.18.18.43.50; author bin; state Exp;
1378: branches ;
1379: next 1.1;
1380:
1381: 1.1
1382: date 91.02.05.16.36.59; author bin; state Exp;
1383: branches ;
1384: next ;
1385:
1386:
1387: desc
1388: @prov by epstein
1389: @
1390:
1391:
1392: 1.2
1393: log
1394: @update provided by epstein
1395: @
1396: text
1397: @/*
1398: * phase 1 of fsck - Check Blocks and Sizes
1399: */
1400:
1401: #include "fsck.h"
1402:
1403: char databuf[BSIZE]; /* buffer for blocks */
1404:
1405: int clrflg; /* indicates when to clear an inode */
1406: int dupflag; /* indicates whether there are any dups */
1407:
1408: int numbad; /* number of bad blocks in the inode */
1409: int numdup; /* number of duplicate blocks in inode */
1410: long numblks; /* number of data blks for size check */
1411: long sparsecnt; /* count for sparse blocks for size check */
1412:
1413: /* The following is a table of the number of direct blocks pointed at by the
1414: * four types of blocks direct, ..., triple-indirect, to help count sparse
1415: * blocks.
1416: */
1417:
1418: daddr_t blockcnt[] = {1, (daddr_t)NBN, (daddr_t)NBN*NBN, (daddr_t)NBN*NBN*NBN};
1419:
1420: phase1()
1421: {
1422: if (!qflag)
1423: printf("Phase 1 : Check Blocks and Sizes\n");
1424: dupflag = FALSE;
1425: inodescan();
1426: if (dupflag)
1427: phase1b();
1428: }
1429:
1430: inodescan()
1431: {
1432: register daddr_t bn;
1433: register struct dinode *dip;
1434: register ino_t ino;
1435: int i;
1436:
1437: ino = 1;
1438:
1439: for (bn=INODEI; bn<isize; bn++) {
1440: if (testblock(bn)) { /* block is bad via inode 1 */
1441: ino += INOPB;
1442: continue;
1443: }
1444: bread(bn, databuf);
1445: clrflg = FALSE;
1446: dip = (struct dinode *) databuf;
1447: for (i=0; i<INOPB; i++) {
1448: candino(dip);
1449: if (inuse(dip) == TRUE) {
1450: if (!fflag)
1451: checkmode(dip, ino);
1452: if ( checkblks(dip, ino) != STOP )
1453: if ( qflag == FALSE )
1454: checksize(dip, ino);
1455: }
1456: candino(dip);
1457: ino++;
1458: dip++;
1459: }
1460: if (clrflg)
1461: bwrite(bn, databuf);
1462: }
1463: }
1464:
1465: /*
1466: * Determine if the given inode is in use.
1467: */
1468:
1469: inuse(dip)
1470: register struct dinode *dip;
1471: {
1472: #ifdef NOT_ALL_ZERO_INODE
1473:
1474: if ( (dip->di_mode != 0) || (dip->di_nlink != 0) )
1475: return(TRUE);
1476: else
1477: return(FALSE);
1478: #endif
1479: #ifdef ALL_ZERO_INODE
1480:
1481: register char *ptr;
1482: register struct dinode *next;
1483:
1484: ptr = (char *) dip;
1485: next = dip + 1;
1486: while (ptr < next)
1487: if (*ptr++ != 0)
1488: return(TRUE);
1489:
1490: return(FALSE);
1491: #endif
1492: }
1493:
1494: /*
1495: * Check the mode of the given inode
1496: */
1497:
1498: checkmode(dip, ino)
1499: register struct dinode *dip;
1500: register ino_t ino;
1501: {
1502: register unsigned short mode;
1503:
1504: mode = dip->di_mode & IFMT;
1505:
1506: switch (mode) {
1507: case IFREG:
1508: setflags(ino, IREG);
1509: return;
1510: case IFDIR:
1511: setflags(ino, IDIR);
1512: return;
1513: case IFCHR:
1514: setflags(ino, ICHR);
1515: return;
1516: case IFBLK:
1517: setflags(ino, IBLK);
1518: return;
1519: case IFPIPE:
1520: setflags(ino, IPIPE);
1521: return;
1522: default:
1523: setflags(ino, UNKNOWN);
1524: break;
1525: }
1526:
1527: switch ( query("Unknown File Type i-number = %u (Clear)", ino) ){
1528: case NO:
1529: return;
1530: case YES:
1531: zeroinode(dip);
1532: setflags(ino, UNALLOC);
1533: clrflg = TRUE;
1534: break;
1535: }
1536: }
1537:
1538: /*
1539: * Zero the given inode
1540: */
1541:
1542: zeroinode(dip)
1543: struct dinode *dip;
1544: {
1545: register char *ptr;
1546: register struct dinode *next;
1547:
1548: lostsize += dip->di_size;
1549: next = dip+1;
1550: ptr = (char *) dip;
1551:
1552: while (ptr < next)
1553: *ptr++ = 0;
1554:
1555: }
1556:
1557: /*
1558: * Check the blocks associated with the given inode to determine
1559: * if any are bad or duplicate
1560: */
1561:
1562: checkblks(dip, ino)
1563: struct dinode *dip;
1564: ino_t ino;
1565: {
1566: daddr_t addrs[NADDR];
1567: register daddr_t bn;
1568: register int i, lev;
1569: register int mode;
1570:
1571: mode = dip->di_mode & IFMT;
1572:
1573: if ( (mode != IFREG) && (mode != IFDIR) )
1574: return(STOP);
1575:
1576: l3tol(addrs, dip->di_addr, NADDR);
1577:
1578: numbad = /* number of bad blocks so far */
1579: numdup = /* num dup blocks so far THIS INODE */
1580: numblks = /* num used data blocks for size chk */
1581: sparsecnt = 0; /* count of missed data blocks */
1582:
1583: for(i=0; i<NADDR; i++)
1584: for (lev=0; lev<4; lev++)
1585: if (i < offsets[lev]) {
1586: if ( (bn=addrs[i]) != 0 ) {
1587: if (doblocks(bn, ino, lev) != OK)
1588: return(STOP);
1589: } else
1590: sparsecnt += blockcnt[lev];
1591: break;
1592: }
1593: return(OK);
1594: }
1595:
1596: /*
1597: * Checks recursively the blocks pointed at via
1598: * the inode list of blocks. 'bn' is the block number,
1599: * 'ino' is the inode referencing it, and 'lev' is the
1600: * level 0 == direct ... 3 = triple-indirect
1601: */
1602:
1603: doblocks(bn, ino, lev)
1604: register daddr_t bn;
1605: ino_t ino;
1606: int lev;
1607: {
1608: char buf[BSIZE];
1609: register daddr_t *bnptr;
1610: register char *end;
1611: register int flag;
1612:
1613: if (lev-- == 0) { /* we have a direct block */
1614: numblks += sparsecnt + 1;
1615: sparsecnt = 0;
1616: return(dodirect(bn, ino));
1617: } else {
1618: end = &buf[BSIZE];
1619: if ( (flag=dodirect(bn, ino)) == OK ) {
1620: bread(bn, buf);
1621: bnptr = (long *) buf;
1622: while ( bnptr < end ) {
1623: bn = *bnptr++;
1624: candaddr(bn);
1625: if ( bn == 0 ) {
1626: sparsecnt += blockcnt[lev];
1627: continue;
1628: }
1629: if ( doblocks(bn, ino, lev) == STOP )
1630: return(STOP);
1631: }
1632: return(OK);
1633: } else
1634: return(flag);
1635: }
1636: }
1637:
1638: /*
1639: * Check the given block to determine if it is bad
1640: * or if it is a duplicate. 'ino' is the inode referencing it
1641: */
1642:
1643: dodirect(bn, ino)
1644: register daddr_t bn;
1645: register ino_t ino;
1646: {
1647: register int flag;
1648:
1649: if ( (flag=checkbad(bn, ino)) == OK )
1650: return( checkdup(bn, ino) );
1651: else
1652: return(flag);
1653: }
1654:
1655: /*
1656: * Check the given block number for being bad.
1657: */
1658:
1659: checkbad(bn, ino)
1660: register daddr_t bn;
1661: ino_t ino;
1662: {
1663: if ( (bn>=isize) && (bn<fsize) )
1664: return(OK);
1665:
1666: else if ( (bn<isize) && (bn>=INODEI) && (ino == 1) ) {
1667: /* bad block is in */
1668: totfree++; /* the inode blocks */
1669: return(OK);
1670: }
1671:
1672: if (!fflag)
1673: orflags(ino, IBAD_IDUP);
1674:
1675: printf("Bad block %U, i-number = %u\n", bn, ino);
1676:
1677: if (numbad++ < MAXBADOK)
1678: return(BAD_DUP);
1679:
1680: switch ( query("Excessive Bad Blocks i-number = %u (Continue)", ino) ){
1681: case NO:
1682: abort();
1683: case YES:
1684: return(STOP);
1685: }
1686: }
1687:
1688:
1689: /*
1690: * Check the given block number for duplicate reference.
1691: */
1692:
1693: checkdup(bn, ino)
1694: register daddr_t bn;
1695: ino_t ino;
1696: {
1697: if ( !testblock(bn) ) {
1698: markblock(bn);
1699: totfree--;
1700: return(OK);
1701: }
1702:
1703: dupflag = TRUE;
1704: if (!fflag)
1705: orflags(ino, IBAD_IDUP);
1706: printf("Dup Block %U, i-number = %u\n", bn, ino);
1707:
1708: if (totdups < DUPTBLSIZE)
1709: dupblck[totdups++] = bn;
1710: else {
1711: switch ( query("DUP Table Overflow (Continue)") ) {
1712: case NO:
1713: abort();
1714: case YES:
1715: return(BAD_DUP);
1716: }
1717: }
1718:
1719: if (numdup++ < MAXDUPOK)
1720: return(BAD_DUP);
1721:
1722: switch ( query("Excessive Dup Blocks i-number = %u (Continue)", ino) ) {
1723: case NO:
1724: abort();
1725: case YES:
1726: return(STOP);
1727: }
1728: }
1729:
1730: /*
1731: * Check For Possible File Size Error
1732: */
1733:
1734: checksize(dip, ino)
1735: register struct dinode *dip;
1736: ino_t ino;
1737: {
1738: register int mode;
1739: register fsize_t size;
1740:
1741: mode = dip->di_mode & IFMT;
1742: size = dip->di_size;
1743:
1744: if ( mode == IFREG )
1745: filesize(ino, size);
1746: else /* mode == IFDIR */
1747: dirsize(dip, ino, size);
1748: }
1749:
1750: dirsize(dip, ino, size)
1751: struct dinode *dip;
1752: ino_t ino;
1753: register fsize_t size;
1754: {
1755: if ( size <= 0 ) {
1756: switch ( query("\
1757: Bad Directory Size, size = %D, i-number = %u (Clear i-node)", size, ino) ) {
1758: case NO:
1759: break;
1760: case YES:
1761: zeroinode(dip);
1762: setflags(ino, UNALLOC);
1763: clrflg = TRUE;
1764: return;
1765: }
1766: }
1767:
1768: if ( size < (2*DSIZE) )
1769: printf("Directory Size too small i-number = %u\n", ino);
1770:
1771: if ( size % sizeof(struct direct) != 0 )
1772: printf("Directory Misaligned i-number = %u\n", ino);
1773:
1774: if (sizerr(size))
1775: printf("Possible Directory Size Error i-number = %u\n", ino);
1776: }
1777:
1778: filesize(ino, size)
1779: ino_t ino;
1780: register fsize_t size;
1781: {
1782: if (sizerr(size))
1783: printf("Possible File Size Error i-number = %u\n", ino);
1784: }
1785:
1786: sizerr(size)
1787: register fsize_t size;
1788: {
1789: register fsize_t calc;
1790:
1791: calc = (unsigned long)numblks*BSIZE;
1792: if ( (size > calc) || ( calc >= (size+BSIZE) ) )
1793: return(TRUE);
1794: else
1795: return(FALSE);
1796: }
1797: @
1798:
1799:
1800: 1.1
1801: log
1802: @Initial revision
1803: @
1804: text
1805: @d152 1
1806: d252 1
1807: a252 1
1808:
1809: @
1810: saligned i-number = %u\n", ino);
1811:
1812: if (sizerr(size))
1813: printf("Possible Directory Size Error i-number = %u\n", ino);
1814: }
1815:
1816: filesize(ino, size)
1817: ino_t infsck/RCS/phase1b.c,v 444 3 3 4676 4753557476 7362 head 1.1;
1818: access ;
1819: symbols ;
1820: locks ;
1821: comment @ * @;
1822:
1823:
1824: 1.1
1825: date 91.02.05.16.37.12; author bin; state Exp;
1826: branches ;
1827: next ;
1828:
1829:
1830: desc
1831: @prov by epstein
1832: @
1833:
1834:
1835:
1836: 1.1
1837: log
1838: @Initial revision
1839: @
1840: text
1841: @/*
1842: * Phase 1b of fsck - Rescan for more Dups
1843: */
1844:
1845: #include "fsck.h"
1846:
1847: extern int numdup; /* declared in phase1.c */
1848:
1849: phase1b()
1850: {
1851: if (!qflag)
1852: printf("Phase 1b: Rescan for more Dups\n");
1853: buildtable();
1854: iscanb();
1855: }
1856:
1857: buildtable()
1858: {
1859: unsigned cntr=0, numdiff=0;
1860: daddr_t bn;
1861:
1862: while (cntr<totdups) {
1863: bn = dupblck[cntr++];
1864: if (!testdup(bn)) {
1865: markdup(bn);
1866: numdiff++;
1867: }
1868: }
1869: totdups = numdiff;
1870: }
1871:
1872: iscanb()
1873: {
1874: register daddr_t bn;
1875: register struct dinode *dip;
1876: register ino_t ino;
1877: int i;
1878:
1879: ino = 1;
1880:
1881: for (bn=INODEI; bn<isize; bn++) {
1882: if (testblock(bn)) { /* block is bad via inode 1 */
1883: ino += INOPB;
1884: continue;
1885: }
1886: bread(bn, databuf);
1887: dip = (struct dinode *) databuf;
1888: for (i=0; i<INOPB; i++) {
1889: candino(dip);
1890: if (inuse(dip) == TRUE)
1891: ckblksb(dip, ino);
1892: if (totdups == 0)
1893: return;
1894: ino++;
1895: dip++;
1896: }
1897: }
1898: }
1899:
1900: /*
1901: * Check the blocks associated with the given inode to find the
1902: * remaining duplicate blocks
1903: */
1904:
1905: ckblksb(dip, ino)
1906: register struct dinode *dip;
1907: register ino_t ino;
1908: {
1909: daddr_t addrs[NADDR];
1910: int i, lev;
1911: int mode;
1912:
1913: mode = dip->di_mode & IFMT;
1914:
1915: if ( (mode != IFREG) && (mode != IFDIR) )
1916: return;
1917:
1918: l3tol(addrs, dip->di_addr, NADDR);
1919:
1920: numdup = 0; /* num dup blocks so far THIS INODE */
1921:
1922: for(i=0; i<NADDR; i++)
1923: for (lev=0; lev<4; lev++)
1924: if (i < offsets[lev]) {
1925: dblocksb(addrs[i], ino, lev);
1926: break;
1927: }
1928: }
1929:
1930: /*
1931: * Checks recursively the blocks pointed at via
1932: * the inode list of blocks. 'bn' is the block number,
1933: * 'ino' is the inode referencing it, and 'lev' is the
1934: * level 0 == direct ... 3 = triple-indirect
1935: */
1936:
1937: dblocksb(bn, ino, lev)
1938: daddr_t bn;
1939: ino_t ino;
1940: int lev;
1941: {
1942: char buf[BSIZE];
1943: int i;
1944: daddr_t *bnptr;
1945:
1946: if (bn == 0)
1947: return(OK);
1948:
1949: switch ( cdupb(bn, ino) ) {
1950: case OK:
1951: if (lev--==0)
1952: return(OK);
1953: bread(bn, buf);
1954: bnptr = (long *) buf;
1955: for (i=0; i<NBN; i++) {
1956: bn = bnptr[i];
1957: candaddr(bn);
1958: if ( dblocksb(bn, ino, lev) == STOP )
1959: return(STOP);
1960: }
1961: return(OK);
1962: case STOP:
1963: return(STOP);
1964: }
1965: }
1966:
1967: /*
1968: * Check the given block number for duplicate reference.
1969: */
1970:
1971: cdupb(bn, ino)
1972: daddr_t bn;
1973: ino_t ino;
1974: {
1975: if ( !testdup(bn) )
1976: return(OK);
1977:
1978: totdups--;
1979: unmarkdup(bn);
1980: if (!fflag)
1981: orflags(ino, IBAD_IDUP);
1982: printf("Dup Block %U, i-number = %u\n", bn, ino);
1983:
1984: return(STOP);
1985: }
1986: @
1987: )
1988: return(OK);
1989: bread(bn, buf);
1990: bnptr = (long *) buf;
1991: for (fsck/RCS/phase2.c,v 444 3 3 17750 4771205232 7212 head 1.2;
1992: access ;
1993: symbols ;
1994: locks bin:1.2;
1995: comment @ * @;
1996:
1997:
1998: 1.2
1999: date 91.03.18.18.44.18; author bin; state Exp;
2000: branches ;
2001: next 1.1;
2002:
2003: 1.1
2004: date 91.02.05.16.37.24; author bin; state Exp;
2005: branches ;
2006: next ;
2007:
2008:
2009: desc
2010: @prov by epstein
2011: @
2012:
2013:
2014: 1.2
2015: log
2016: @update provided by epstein
2017: @
2018: text
2019: @/*
2020: * phase 2 of fsck - Check Pathnames
2021: */
2022:
2023: #include "fsck.h"
2024: #include <pwd.h>
2025:
2026: #define MAXDEPTH 50
2027: struct direct *path[MAXDEPTH];
2028: int depth;
2029: int fixflag; /* flags when must rewrite databuf */
2030: daddr_t blocknum; /* Current block num read in */
2031:
2032: typedef struct list {
2033: struct direct d_entry;
2034: struct list *next;
2035: } list;
2036:
2037: char buf2[BSIZE]; /* buffer for blocks */
2038: daddr_t cdbn; /* current logical block number */
2039:
2040: /* Format errors, args to blkerr() */
2041:
2042: #define NULLNAME 5
2043: #define NULLPAD 6
2044: #define SLASHES 7
2045: #define DOT 8
2046: #define DOTDOT 9
2047:
2048: phase2()
2049: {
2050: if (!qflag)
2051: printf("Phase 2 : Check Pathnames\n");
2052: checkroot();
2053: depth = 0;
2054: checkpath(ROOTIN);
2055: }
2056:
2057:
2058: checkroot()
2059: {
2060: if ( (flags(ROOTIN)&MODEMASK) == UNALLOC )
2061: fatal("Root i-node is unallocated. Terminating");
2062:
2063: if ( (flags(ROOTIN)&MODEMASK) != IDIR ) {
2064: switch ( query("Root i-node is not a directory (FIX)") ){
2065: case YES:
2066: fixroot();
2067: break;
2068: case NO:
2069: abort();
2070: }
2071: }
2072:
2073: if ( badblks(ROOTIN) ){
2074: switch ( query("Dup/Bad blocks in root i-node (Continue)") ) {
2075: case YES:
2076: break;
2077: case NO:
2078: abort();
2079: }
2080: }
2081: linkincr(ROOTIN); /* (?) Feature (?) of mkfs is */
2082: /* that root inode of a file */
2083: /* system has a link count one */
2084: /* too large. */
2085: }
2086:
2087: fixroot()
2088: {
2089: register struct dinode *dip;
2090:
2091: if (!writeflg)
2092: fatal("File System Read-Only (NO WRITE)\n");
2093:
2094: setflags(ROOTIN, (flags(ROOTIN) & ~MODEMASK) | IDIR);
2095:
2096: /* Save change to disk */
2097:
2098: dip = ptrino(ROOTIN, databuf);
2099: dip->di_mode &= (~IFMT);
2100: dip->di_mode |= IFDIR;
2101: writeino(ROOTIN, databuf);
2102: }
2103:
2104: #define myinum ( (depth>0) ? path[depth-1]->d_ino : ROOTIN )
2105: #define popinum ( (depth>1) ? path[depth-2]->d_ino : ROOTIN )
2106:
2107: char *memory = "Can't malloc memory, phase 2";
2108:
2109: list *
2110: procfiles(addrs, length)
2111: daddr_t *addrs;
2112: fsize_t length;
2113: {
2114: register struct direct *elemnt;
2115: register list *first, *ptr;
2116:
2117: if ((first=ptr=(list *)malloc(sizeof(list)))==NULL)
2118: fatal(memory);
2119: first->d_entry.d_ino = 0;
2120: first->next = NULL;
2121: if ( length < DSIZE )
2122: return( first );
2123: cdbn = 0;
2124: nextblock(addrs);
2125: fixflag = FALSE;
2126: elemnt = (struct direct *) databuf;
2127: cdots(elemnt++, ".", myinum, DOT);
2128: ++numfiles;
2129: if ( (length-=DSIZE) < DSIZE )
2130: return( first );
2131: cdots(elemnt++, "..", popinum, DOTDOT);
2132: ++numfiles;
2133: length -= DSIZE;
2134:
2135: while ( length >= DSIZE ) {
2136: while ( (elemnt<&databuf[BSIZE]) && (length>=DSIZE) ) {
2137: if (chck(elemnt)==IDIR) {
2138: copy(elemnt, &ptr->d_entry,
2139: sizeof(struct direct));
2140: if ((ptr->next=(list *)malloc(sizeof(list))) ==
2141: NULL)
2142: fatal(memory);
2143: ptr = ptr->next;
2144: ptr->d_entry.d_ino = 0;
2145: ptr->next = NULL;
2146: }
2147: elemnt++;
2148: length -= DSIZE;
2149: }
2150: if (fixflag && (fixblock(addrs) == NUL) )
2151: fixblkerr();
2152: nextblock(addrs);
2153: fixflag = FALSE;
2154: elemnt = (struct direct *) databuf;
2155: }
2156: return(first);
2157: }
2158:
2159: candblock(dptr)
2160: register struct direct *dptr;
2161: {
2162: register int num, i;
2163:
2164: num = BSIZE/sizeof(struct direct);
2165: for (i=0; i<num; i++)
2166: canino(dptr[i].d_ino);
2167: }
2168:
2169: nextblock(addrs)
2170: register daddr_t *addrs;
2171: {
2172: register daddr_t bn;
2173:
2174: if ( (bn=imap(addrs, cdbn++)) == 0 ) {
2175: bclear(databuf, BSIZE);
2176: return;
2177: }
2178: bread(bn, databuf);
2179: candblock(databuf);
2180: blocknum = bn;
2181: }
2182:
2183: fixblock(addrs)
2184: daddr_t *addrs;
2185: {
2186: daddr_t bn;
2187:
2188: if ( (bn=imap(addrs, cdbn-1)) == 0 )
2189: return(NUL);
2190: candblock(databuf);
2191: bwrite(bn, databuf);
2192: return(TRUE);
2193: }
2194:
2195: fixblkerr()
2196: {
2197: fatal("Fixblock error.");
2198: }
2199:
2200: copy(from, to, size)
2201: register char *from, *to;
2202: register int size;
2203: {
2204: while (size--)
2205: *to++=*from++;
2206: }
2207:
2208: cdots(elemnt, dots, ino, type)
2209: register struct direct *elemnt;
2210: char *dots;
2211: ino_t ino; /* what the inode number should be */
2212: int type;
2213: {
2214: register char *name = elemnt->d_name;
2215: register ino_t inum;
2216:
2217: inum = elemnt->d_ino;
2218: if ( (strcmp(name, dots) != 0) || (inum != ino) ||
2219: (format(name) != GOOD) ) {
2220: blkerr(type);
2221: return;
2222: }
2223: linkincr(inum);
2224: }
2225:
2226: format(name)
2227: register char *name;
2228: {
2229: register char *ptr=name;
2230: register char *end=&name[DIRSIZ];
2231:
2232: while ( (ptr<end) && (*ptr++ != '\0') ) ;
2233:
2234: if ( (ptr-1) == name )
2235: return(NULLNAME);
2236:
2237: if (ptr<end) {
2238: while ( (ptr<end) && (*ptr++ == '\0') ) ;
2239: if (ptr!=end)
2240: return(NULLPAD);
2241: }
2242:
2243: ptr = name;
2244: while (ptr < end)
2245: if (*ptr++ == '/')
2246: return(SLASHES);
2247:
2248: return(GOOD);
2249: }
2250:
2251:
2252: blkerr(type)
2253: int type;
2254: {
2255: char *errname;
2256:
2257: switch(type) {
2258: case NULLNAME:
2259: errname = "Null name";
2260: break;
2261: case NULLPAD:
2262: errname = "Non null padded";
2263: break;
2264: case SLASHES:
2265: errname = "Embedded slashes in";
2266: break;
2267: case DOT:
2268: errname = "Inconsistent .";
2269: break;
2270: case DOTDOT:
2271: errname = "Inconsistent ..";
2272: break;
2273: default:
2274: errname = "Bad";
2275: break;
2276: }
2277:
2278: printf("%s entry in block %U in directory\n", errname, blocknum);
2279: pinfo(myinum);
2280: pname(path[--depth]->d_name);
2281: depth++;
2282: }
2283:
2284: chck(elemnt)
2285: register struct direct *elemnt;
2286: {
2287: register ino_t inum;
2288: register char *name;
2289: int type;
2290:
2291: inum = elemnt->d_ino;
2292: if ( inum == 0 )
2293: return(UNALLOC);
2294:
2295: name = elemnt->d_name;
2296: if ( (type=format(name)) != GOOD )
2297: blkerr(type);
2298:
2299: if (inum>ninodes) {
2300: if ( irange(inum, name) )
2301: zeroent(elemnt);
2302: return(UNALLOC);
2303: }
2304:
2305: if ( (flags(inum)&ALLOCMASK)==UNALLOC ) {
2306: if ( unalloc(inum, name) )
2307: zeroent(elemnt);
2308: return(UNALLOC);
2309: }
2310:
2311: if ( badblks(inum) ) {
2312: if ( baddup(inum, name) ) {
2313: zeroent(elemnt);
2314: return(UNALLOC);
2315: }
2316: if ( (flags(inum)&MODEMASK)==IDIR )
2317: return(UNALLOC);
2318: }
2319:
2320: linkincr(inum);
2321: numfiles++;
2322: return( flags(inum)&MODEMASK );
2323: }
2324:
2325: zeroent(elemnt)
2326: struct direct *elemnt;
2327: {
2328: elemnt->d_ino = 0;
2329: fixflag = TRUE;
2330: }
2331:
2332: pname(name)
2333: char *name;
2334: {
2335: int i=0;
2336:
2337: while (i<depth)
2338: prdirsize(path[i++]->d_name);
2339: prdirsize(name);
2340: putchar('\n');
2341: }
2342:
2343: prdirsize(name)
2344: char *name;
2345: {
2346: if (name[DIRSIZ-1] == '\0')
2347: printf("/%s", name);
2348: else
2349: printf("/%*s", DIRSIZ, name);
2350: }
2351:
2352: fsize_t
2353: pinfo(inum)
2354: ino_t inum;
2355: {
2356: register struct dinode *dip;
2357: register struct passwd *pwd;
2358:
2359: if ( (dip=ptrino(inum, buf2)) == NULL ) {
2360: printf("i-number = %u is in a bad inode block.\n", inum);
2361: return(0);
2362: }
2363:
2364: printf("i-number = %u, ", inum);
2365: if ( (pwd=getpwuid(dip->di_uid)) != NULL )
2366: printf("Owner=%s, ", pwd->pw_name);
2367: else
2368: printf("Owner=%u, ", dip->di_uid);
2369: printf(" Mode=0%o\n", dip->di_mode);
2370: printf("Size=%U, Mtime=%s", dip->di_size, ctime(&dip->di_mtime));
2371: return(dip->di_size);
2372: }
2373:
2374: char *remove = "(Remove)";
2375:
2376: irange(inum, name)
2377: ino_t inum;
2378: char *name;
2379: {
2380: printf("I-number is out of range I=%u\n", inum);
2381: pname(name);
2382: return(action(remove));
2383: }
2384:
2385: unalloc(inum, name)
2386: ino_t inum;
2387: char *name;
2388: {
2389: fsize_t size;
2390:
2391: printf("Unallocated\n");
2392: size = pinfo(inum);
2393: pname(name);
2394: if ( (daction != NO) && (size == 0) && (mounted == FALSE) ) {
2395: printf("%s [Forced - Yes]\n", remove);
2396: return(YES);
2397: }
2398: return(action(remove));
2399: }
2400:
2401: baddup(inum, name)
2402: ino_t inum;
2403: char *name;
2404: {
2405: register int mode = flags(inum)&MODEMASK;
2406:
2407: printf("Bad or Dup blocks in %s\n",(mode==IDIR) ? "Directory" : "File");
2408: pinfo(inum);
2409: pname(name);
2410: return(action(remove));
2411: }
2412:
2413: checkpath(ino)
2414: register ino_t ino;
2415: {
2416: static daddr_t addrs[NADDR];
2417: static struct dinode *dip;
2418: static list *temp;
2419: register list *ptr;
2420:
2421: if ( (flags(ino)&VISITED)==VISITED ) {
2422: circle(ino);
2423: return;
2424: } else
2425: orflags(ino, VISITED);
2426:
2427: dip = ptrino(ino, databuf);
2428: l3tol(addrs, dip->di_addr, NADDR);
2429:
2430: if ( (dip->di_mode&IFMT) != IFDIR )
2431: fatal("Tried to checkpath i-node %u which is not dir.\n", ino);
2432:
2433: ptr = procfiles(addrs, dip->di_size);
2434:
2435: while (ptr->d_entry.d_ino) {
2436: if (depth >= MAXDEPTH)
2437: toolong();
2438: path[depth++] = &ptr->d_entry;
2439: checkpath(ptr->d_entry.d_ino);
2440: depth--;
2441: temp = ptr;
2442: ptr = ptr->next;
2443: free(temp);
2444: }
2445: free(ptr);
2446: }
2447:
2448: circle(ino)
2449: ino_t ino;
2450: {
2451: printf("I-node %u is a multiply referenced directory i-node.\n", ino);
2452: }
2453:
2454: toolong()
2455: {
2456: printf("Name too long.\n");
2457: pname("\0");
2458: abort();
2459: }
2460:
2461:
2462: @
2463:
2464:
2465: 1.1
2466: log
2467: @Initial revision
2468: @
2469: text
2470: @d102 3
2471: d110 3
2472: d114 2
2473: a115 2
2474: numfiles += 2;
2475: length -= 2*DSIZE; /* for the . & .. entries */
2476: d127 1
2477: @
2478: r->d_entry.d_ino) {
2479: iffsck/RCS/phase3.c,v 444 3 3 12752 5050254731 7207 head 1.2;
2480: branch ;
2481: access ;
2482: symbols ;
2483: locks bin:1.2;
2484: comment @ * @;
2485:
2486:
2487: 1.2
2488: date 91.08.08.09.48.33; author bin; state Exp;
2489: branches ;
2490: next 1.1;
2491:
2492: 1.1
2493: date 91.02.05.16.37.54; author bin; state Exp;
2494: branches ;
2495: next ;
2496:
2497:
2498: desc
2499: @prov by epstein (post 310)
2500: @
2501:
2502:
2503: 1.2
2504: log
2505: @updated by epstein to properly handle directory allocations.
2506: @
2507: text
2508: @/*
2509: * phase 3 of fsck - Check Connectivity
2510: */
2511:
2512: #include "fsck.h"
2513:
2514: char *lostname = "lost+found";
2515:
2516: phase3()
2517: {
2518: ino_t i;
2519:
2520: if (!qflag)
2521: printf("Phase 3 : Check Connectivity\n");
2522: for (i=FIRSTIN; i<=ninodes; i++)
2523: if ( ((flags(i)&MODEMASK) == IDIR) &&
2524: (linkctr(i) == 0) ) {
2525: orflags(i, UNREFDIR);
2526: markchildren(i);
2527: }
2528:
2529: for (i=FIRSTIN; i<ninodes; i++)
2530: if ( (flags(i)&(UNREFDIR|CHILDDIR)) == UNREFDIR )
2531: unrefdir(i);
2532: }
2533:
2534: markchildren(ino)
2535: ino_t ino;
2536: {
2537: struct dinode *dip;
2538: struct direct *element;
2539: daddr_t addrs[NADDR];
2540: ino_t inumber;
2541: fsize_t length;
2542:
2543: if ( badblks(ino) )
2544: return;
2545: dip = ptrino(ino, databuf);
2546: if ( (length=dip->di_size) <= 0 )
2547: return;
2548: l3tol(addrs, dip->di_addr, NADDR);
2549: cdbn = 0;
2550: nextblock(addrs);
2551: element = (struct direct *) databuf;
2552: element += 2; /* skip over . and .. entries */
2553: if ( (length-=2*DSIZE) <= 0 )
2554: return;
2555:
2556: while ( length >= DSIZE ) {
2557: while ( (element<&databuf[BSIZE]) && (length>=DSIZE) ) {
2558: if ( ((inumber=element->d_ino) != 0) &&
2559: ((flags(inumber)&MODEMASK)==IDIR) &&
2560: (inumber!=ino) )
2561: orflags(inumber, CHILDDIR);
2562: element++;
2563: length -= DSIZE;
2564: }
2565: nextblock(addrs);
2566: element = (struct direct *) databuf;
2567: }
2568: }
2569:
2570: char *reconnect = "(Reconnect)";
2571:
2572: unrefdir(ino)
2573: ino_t ino;
2574: {
2575: printf("Unref Dir\n");
2576: if( (pinfo(ino) == 0) || (daction == NO) || (mounted == TRUE) ) {
2577: if ( action(reconnect) == FALSE )
2578: return;
2579: } else
2580: printf("%s FORCED\n", reconnect);
2581:
2582: connect(ino, IDIR);
2583: }
2584:
2585: #define CONNECT 1
2586: #define NOCONNECT 0
2587:
2588: connect(ino, type)
2589: ino_t ino;
2590: int type;
2591: {
2592: ino_t lostino;
2593: struct dinode *dip;
2594: daddr_t addrs[NADDR];
2595: fsize_t length;
2596: struct direct *element;
2597: int chgino = FALSE;
2598:
2599: if ( ((lostino=lostfound()) == NUL) ||
2600: ((flags(lostino)&MODEMASK) != IDIR) ||
2601: ( badblks(lostino) ) ) {
2602: nolost();
2603: if (type==IDIR)
2604: traverse(NOCONNECT, ino, lostino);
2605: return(FAILURE);
2606: }
2607:
2608: dip = ptrino(lostino, buf2);
2609: l3tol(addrs, dip->di_addr, NADDR);
2610: length = dip->di_size;
2611: cdbn = 0;
2612: while ( length>=DSIZE ) {
2613: nextblock(addrs);
2614: element = (struct direct *) databuf;
2615: while ( element<&databuf[BSIZE] ) {
2616: length -= DSIZE;
2617: if ( element->d_ino == 0 ) {
2618: element->d_ino = ino;
2619: strncpy(element->d_name, nameit(ino), DIRSIZ);
2620: if ( fixblock(addrs) == NUL )
2621: fixblkerr();
2622: linkincr(ino);
2623: numfiles++;
2624: if ( length<0 ) {
2625: dip->di_size -= length;
2626: chgino = TRUE;
2627: }
2628: if ( (type == IDIR) &&
2629: (connected(ino, lostino)==YES) ) {
2630: dip->di_nlink++;
2631: writeino(lostino, buf2);
2632: traverse(CONNECT, ino, lostino);
2633: } else if (chgino) {
2634: writeino(lostino, buf2);
2635: }
2636: return(SUCCESS);
2637: }
2638: element++;
2639: }
2640: }
2641:
2642: noroom();
2643: if (type == IDIR)
2644: traverse(NOCONNECT, ino, lostino);
2645: return(FAILURE);
2646: }
2647:
2648: traverse(flag, ino, lostino)
2649: int flag;
2650: ino_t ino, lostino;
2651: {
2652: struct direct dirlost, nothing, newtree;
2653:
2654: dirinit(&dirlost, lostino, lostname);
2655: dirinit(¬hing, 0, "??");
2656: dirinit(&newtree, ino, nameit(ino));
2657: depth = 0;
2658: if (flag == CONNECT)
2659: path[depth++] = &dirlost;
2660: else
2661: path[depth++] = ¬hing;
2662:
2663: path[depth++] = &newtree;
2664: checkpath(ino);
2665: }
2666:
2667: dirinit(element, ino, name)
2668: struct direct *element;
2669: ino_t ino;
2670: char *name;
2671: {
2672: element->d_ino = ino;
2673: strncpy(element->d_name, name, DIRSIZ);
2674: }
2675:
2676: connected(ino, lostino)
2677: ino_t ino; /* inumber just reconnected */
2678: ino_t lostino; /* inumber of lostfound directory */
2679: {
2680: struct dinode *dip;
2681: daddr_t addrs[NADDR];
2682: fsize_t length;
2683: struct direct *element;
2684:
2685: if ( badblks(ino) ) {
2686: badconnect(ino);
2687: return(NO);
2688: }
2689: dip = ptrino(ino, databuf);
2690: l3tol(addrs, dip->di_addr, NADDR);
2691: length = dip->di_size;
2692: cdbn = 0;
2693: while ( length >= DSIZE ) {
2694: nextblock(addrs);
2695: element = (struct direct *) databuf;
2696: while ( (element<&databuf[BSIZE]) && (length>=DSIZE) ) {
2697: if ( strcmp(element->d_name, "..") == 0 ) {
2698: printf("Dir i-number = %u connected. ", ino);
2699: printf("Parent was i-number = %u.\n",
2700: element->d_ino);
2701: element->d_ino = lostino;
2702: if ( fixblock(addrs) == NUL )
2703: fixblkerr();
2704: return(YES);
2705: }
2706: length -= DSIZE;
2707: element++;
2708: }
2709: }
2710: noparent(ino);
2711: return(NO);
2712: }
2713:
2714: badconnect(ino)
2715: ino_t ino;
2716: {
2717: printf("Dir i-number = %u connected. It has bad/dup blocks.\n", ino);
2718: }
2719:
2720: noparent(ino)
2721: ino_t ino;
2722: {
2723: printf("Dir i-number = %u connected. It has no .. entry.\n", ino);
2724: }
2725:
2726: ino_t
2727: lostfound()
2728: {
2729: static daddr_t addrs[NADDR];
2730: struct dinode *dip;
2731: struct direct *element;
2732: fsize_t length;
2733:
2734: dip = ptrino(ROOTIN, databuf);
2735: l3tol(addrs, dip->di_addr, NADDR);
2736: length = dip->di_size;
2737: cdbn = 0;
2738: while ( length>=DSIZE ) {
2739: nextblock(addrs);
2740: element = (struct direct *) databuf;
2741: while ( (element<&databuf[BSIZE]) && (length>=DSIZE) ) {
2742: if ( strcmp(element->d_name, lostname) == 0 )
2743: return(element->d_ino);
2744: length -= DSIZE;
2745: element++;
2746: }
2747: }
2748:
2749: return(NUL);
2750: }
2751:
2752: nolost()
2753: {
2754: printf("Sorry. No %s directory.\n", lostname);
2755:
2756: }
2757:
2758: noroom()
2759: {
2760: printf("Sorry. No space in %s directory.\n", lostname);
2761: }
2762:
2763: char namebuf[DIRSIZ];
2764:
2765: char *
2766: nameit(ino)
2767: register ino_t ino;
2768: {
2769: register int i = DIRSIZ-1;
2770:
2771: namebuf[i] = '\0';
2772: while ( (ino != 0) && (i>0) ) {
2773: namebuf[--i] = '0' + ino%10;
2774: ino = ino/10;
2775: }
2776: return(&namebuf[i]);
2777: }
2778: @
2779:
2780:
2781: 1.1
2782: log
2783: @Initial revision
2784: @
2785: text
2786: @d109 1
2787: a130 1
2788: length -= DSIZE;
2789: @
2790: eturn(element->d_ino);fsck/RCS/phase4.c,v 444 3 3 12033 4771205260 7202 head 1.2;
2791: access ;
2792: symbols ;
2793: locks bin:1.2;
2794: comment @ * @;
2795:
2796:
2797: 1.2
2798: date 91.03.18.18.44.48; author bin; state Exp;
2799: branches ;
2800: next 1.1;
2801:
2802: 1.1
2803: date 91.02.05.16.38.17; author bin; state Exp;
2804: branches ;
2805: next ;
2806:
2807:
2808: desc
2809: @prov by epstein (post 310)
2810: @
2811:
2812:
2813: 1.2
2814: log
2815: @update provided by epstein
2816: @
2817: text
2818: @/*
2819: * phase 4 of fsck - Check Reference Counts
2820: */
2821:
2822: #include "fsck.h"
2823:
2824: extern char *reconnect;
2825: fsize_t lostsize;
2826:
2827: phase4()
2828: {
2829: ino_t i;
2830: short actlink;
2831:
2832: if (!qflag)
2833: printf("Phase 4 : Check Reference Counts\n");
2834: for (i=FIRSTIN; i<=ninodes; i++) {
2835: if ( badblks(i) )
2836: if ( bddp(i) == YES )
2837: continue; /* inode zeroed */
2838:
2839: if ( (linkctr(i) == 0) &&
2840: ((flags(i)&MODEMASK) != IDIR) &&
2841: ((flags(i)&ALLOCMASK) != UNALLOC) )
2842: if ( unreflink(i) == YES )
2843: continue; /* inode zeroed */
2844:
2845: if ( (linkctr(i) == 0) &&
2846: ((flags(i)&ALLOCMASK) != UNALLOC) )
2847: if ( unrefclr(i) == YES )
2848: continue; /* inode zeroed */
2849:
2850: if ( (actlink=getlink(i)) == (-1) ) {
2851: i += INOPB-1;
2852: continue; /* bad inode block */
2853: }
2854:
2855: if ( actlink != linkctr(i) )
2856: linkprob(i, actlink); /* fix link count */
2857: }
2858:
2859: freeilist();
2860: }
2861:
2862: short
2863: getlink(inum)
2864: register ino_t inum;
2865: {
2866: register unsigned offset;
2867: static ibuf[BSIZE];
2868: register struct dinode *dip;
2869: register daddr_t bn;
2870:
2871: offset = iblocko(inum);
2872: if ( (offset==0) || (inum==FIRSTIN) ) {
2873: bn = iblockn(inum);
2874: if ( (testblock(bn)) && (inum!=FIRSTIN) )
2875: return(-1);
2876: bread(bn, ibuf);
2877: }
2878: dip = ((struct dinode *) ibuf) + offset;
2879: candino(dip);
2880: return(dip->di_nlink);
2881: }
2882:
2883: char *clearit = "(Clear i-node)";
2884:
2885: unreflink(ino)
2886: ino_t ino;
2887: {
2888: fsize_t size;
2889:
2890: if ( (qflag == TRUE) && ((flags(ino)&MODEMASK) == IPIPE) ) {
2891: doclear(ino);
2892: return(YES);
2893: }
2894:
2895: printf("Unref %s\n", typename(ino));
2896: size = pinfo(ino);
2897: if ( (daction != NO) && (size == 0) && (mounted == FALSE)
2898: && ((flags(ino)&MODEMASK) == IREG) ) {
2899: printf("%s [Forced - Yes]\n", clearit);
2900: doclear(ino);
2901: return(YES);
2902: }
2903: if ( action(reconnect) == TRUE )
2904: if( connect(ino, IREG) == FAILURE ) /* connect back in the */
2905: return(askclear(ino)); /* non dir inode */
2906:
2907: return(NO);
2908: }
2909:
2910: askclear(ino)
2911: ino_t ino;
2912: {
2913: if ( action(clearit) == TRUE ) {
2914: doclear(ino);
2915: return(YES);
2916: }
2917: return(NO);
2918: }
2919:
2920: doclear(ino)
2921: ino_t ino;
2922: {
2923: struct dinode *dip;
2924:
2925: dip = ptrino(ino, databuf);
2926: zeroinode(dip);
2927: writeino(ino, databuf);
2928: setflags(ino, UNALLOC);
2929: setlinkctr(ino, 0);
2930: }
2931:
2932: char *adjust = "(Adjust)";
2933:
2934: linkprob(ino, actlink)
2935: ino_t ino;
2936: short actlink;
2937: {
2938: printf("Link Count discrepancy in %s\n", typename(ino));
2939: pinfo(ino);
2940: printf("Count = %u, should be %u ", actlink, linkctr(ino));
2941: if ( action(adjust) == TRUE )
2942: chglink(ino);
2943: }
2944:
2945: chglink(ino)
2946: ino_t ino;
2947: {
2948: struct dinode *dip;
2949:
2950: dip = ptrino(ino, databuf);
2951: dip->di_nlink = linkctr(ino);
2952: writeino(ino, databuf);
2953: }
2954:
2955: unrefclr(ino)
2956: ino_t ino;
2957: {
2958: printf("Unref %s\n", typename(ino));
2959: pinfo(ino);
2960: return(askclear(ino));
2961: }
2962:
2963: bddp(ino)
2964: ino_t ino;
2965: {
2966: printf("Bad/Dup blocks in %s\n", typename(ino));
2967: pinfo(ino);
2968: return(askclear(ino));
2969: }
2970:
2971: char *fixit = "(FIX)";
2972:
2973: freeilist()
2974: {
2975: ino_t i, count=0;
2976: daddr_t bn;
2977:
2978: for (i=FIRSTIN; i<=ninodes; i++)
2979: if ( (flags(i)&ALLOCMASK) == UNALLOC )
2980: count++;
2981:
2982: for (bn=INODEI+1; bn<isize; bn++) /* block # INODEI can't */
2983: if ( testblock(bn) ) /* be bad since ROOTIN */
2984: count -= INOPB; /* is in it, otherwise */
2985: /* big time bad news. */
2986: if ( sbp->s_tinode != count )
2987: if ( (qflag==FALSE) && (daction!=NO) ) {
2988: printf("Free i-node count wrong in superblock. ");
2989: if ( action(fixit) == TRUE ) {
2990: sbp->s_tinode = count;
2991: sbpfix = TRUE;
2992: }
2993: } else {
2994: sbp->s_tinode = count;
2995: sbpfix = TRUE;
2996: }
2997:
2998: if ( (daction!=NO) &&
2999: ( (sflag==TRUE) || (sbpfix==TRUE) || (badilist()==BAD) ) )
3000: rebuild();
3001:
3002: }
3003:
3004: badilist()
3005: {
3006: ino_t i, inum;
3007: unsigned numfree;
3008: daddr_t bn;
3009:
3010: if ( (numfree=(unsigned) sbp->s_ninode) > NICINOD )
3011: return(BAD);
3012: for (i=0; i<numfree; i++) {
3013: inum = sbp->s_inode[i];
3014: bn = iblockn(inum);
3015: if ( (testblock(bn)) && (bn!=INODEI) )
3016: return(BAD);
3017: if ( (inum < FIRSTIN) || (inum > ninodes) )
3018: return(BAD);
3019: if ( (flags(inum)&ALLOCMASK) != UNALLOC )
3020: return(BAD);
3021: if ( flags(inum)&IFREELIST )
3022: return(BAD); /* dup in ifree list */
3023: orflags(inum, IFREELIST);
3024: }
3025: return(GOOD);
3026: }
3027:
3028: rebuild()
3029: {
3030: daddr_t bn;
3031: ino_t i;
3032: int index;
3033:
3034: sbpfix = TRUE;
3035: for (i=FIRSTIN, index=0; (i<=ninodes) && (index<NICINOD); i++) {
3036: if ( (flags(i)&ALLOCMASK) == UNALLOC ) {
3037: bn = iblockn(i);
3038: if ( (!testblock(bn)) || (bn==INODEI) )
3039: index++;
3040: }
3041: }
3042: sbp->s_ninode = index;
3043: for (i=FIRSTIN; (i<=ninodes) && (index>0); i++) {
3044: if ( (flags(i)&ALLOCMASK) == UNALLOC ) {
3045: bn = iblockn(i);
3046: if ( (!testblock(bn)) || (bn==INODEI) )
3047: sbp->s_inode[--index] = i;
3048: }
3049: }
3050: printf("Free i-node list in superblock rebuilt.\n");
3051: }
3052: @
3053:
3054:
3055: 1.1
3056: log
3057: @Initial revision
3058: @
3059: text
3060: @a16 1
3061: lostsize = 0;
3062: a108 1
3063: lostsize += dip->di_size;
3064: d181 2
3065: a182 1
3066: if ( (daction!=NO) && ((sbpfix==TRUE) || (badilist()==BAD)) )
3067: d214 2
3068: a215 2
3069: ino_t i = FIRSTIN;
3070: int index = 0;
3071: d218 1
3072: a218 1
3073: while ( (i<=ninodes) && (index<NICINOD) ) {
3074: d222 1
3075: a222 1
3076: sbp->s_inode[index++] = i;
3077: a223 1
3078: i++;
3079: a224 1
3080:
3081: d226 7
3082: @
3083: bn = iblockn(i);
3084: if ( (!testblock(bn)) || (bn==INODEI) )
3085: sbp->s_inode[--index] = i;
3086: }
3087: }
3088: printf("Free i-node list in superblock rebuilt.\n");
3089: }
3090: @
3091:
3092:
3093: 1.1
3094: log
3095: @Initial revision
3096: @
3097: text
3098: @a16 1
3099: lostsize = 0;
3100: a108 1
3101: lostsize += dip->di_size;
3102: d181 2
3103: a182 1
3104: if ( (daction!=NO) && ((sbpfix==TRUE) || (badilist()==BAD)) )
3105: d214 2
3106: a215 2
3107: ino_t i = FIRSTIN;
3108: int index = 0;
3109: d218 1
3110: a218 1
3111: while ( (i<=ninodes) && (index<NICINOD) ) {
3112: d222 1
3113: a222 1
3114: sbp->s_inode[index++] = i;
3115: a223fsck/RCS/phase5.c,v 444 3 3 7463 4771205275 7204 head 1.2;
3116: access ;
3117: symbols ;
3118: locks bin:1.2;
3119: comment @ * @;
3120:
3121:
3122: 1.2
3123: date 91.03.18.18.45.05; author bin; state Exp;
3124: branches ;
3125: next 1.1;
3126:
3127: 1.1
3128: date 91.02.05.16.38.33; author bin; state Exp;
3129: branches ;
3130: next ;
3131:
3132:
3133: desc
3134: @prov by epstein (phase5.c)
3135: @
3136:
3137:
3138: 1.2
3139: log
3140: @update provided by epstein
3141: @
3142: text
3143: @/*
3144: * phase 5 of fsck - Check Free List
3145: */
3146:
3147: #include "fsck.h"
3148:
3149: daddr_t badcnt; /* Number of bad blocks in free list */
3150: daddr_t dupcnt; /* Number of dup blocks in free list */
3151: int badflag; /* Bad free list flag */
3152: int fixerup; /* Flag to salvage free list */
3153:
3154: phase5()
3155: {
3156: struct fblk *fbp;
3157: unsigned size;
3158:
3159: if (!qflag)
3160: printf("Phase 5 : Check Free List\n");
3161: fbp = (struct fblk *) &sbp->s_nfree;
3162: size = (unsigned) ((fsize+NBPC-1)/NBPC) * sizeof(char);
3163: copyV(size);
3164: badcnt = dupcnt = 0;
3165: badflag = FALSE;
3166: freetrav(fbp);
3167: fixerup = FALSE;
3168: if (badflag || sflag)
3169: asksalvage();
3170: }
3171:
3172:
3173: #define IGNORE 3 /* Return Possibilities from chk() */
3174: #define ABORT 4 /* as well as perhaps GOOD and BAD */
3175:
3176: freetrav(fbp)
3177: struct fblk *fbp;
3178: {
3179: daddr_t total=0;
3180: int i, flag;
3181:
3182: while ( fbp->df_nfree != 0 ) {
3183: if ( (unsigned) fbp->df_nfree > NICFREE ) {
3184: badflag = TRUE;
3185: printf("Bad freeblock count.\n");
3186: break;
3187: }
3188: for (i=1; i<fbp->df_nfree; i++) {
3189: if ( (flag=chk(fbp->df_free[i])) == GOOD ) {
3190: total++;
3191: continue;
3192: }
3193: if (flag == BAD)
3194: continue;
3195: break; /* break for IGNORE or ABORT */
3196: }
3197: if ( (flag == IGNORE) || (flag == ABORT) )
3198: break;
3199: if ( chk(fbp->df_free[0]) != GOOD )
3200: break;
3201: total++;
3202: bread(fbp->df_free[0], databuf);
3203: fbp = (struct fblk *) databuf;
3204: if ( !canfblk(fbp) ) {
3205: badflag = TRUE;
3206: printf("Bad freeblock count.\n");
3207: break;
3208: }
3209: }
3210:
3211: #if 0
3212: printf("Total traversed free blocks = %U\n", total);
3213: printf("Total free blocks by Superblock = %U\n", sbp->s_tfree);
3214: printf("Running total free blocks = %U\n", totfree);
3215: #endif
3216:
3217: if ( flag == ABORT ) { /* To Terminate fsck on this */
3218: badflag = FALSE; /* File System, because of */
3219: return; /* excessive dup or bad blocks */
3220: }
3221:
3222: if ( sbp->s_tfree != totfree )
3223: if ( (qflag==FALSE) && (daction!=NO) ) {
3224: printf("Free Block count wrong in superblock. ");
3225: if ( action(fixit) == TRUE ) {
3226: sbp->s_tfree = totfree;
3227: sbpfix = TRUE;
3228: }
3229: } else {
3230: sbp->s_tfree = totfree;
3231: sbpfix = TRUE;
3232: }
3233:
3234: report("%U Bad Block%s in Free List\n", badcnt);
3235: report("%U Dup Block%s in Free List\n", dupcnt);
3236: report("%U Block%s missing\n", totfree - total);
3237:
3238: }
3239:
3240: report(message, num)
3241: char *message;
3242: daddr_t num;
3243: {
3244: if ( num != 0 ) {
3245: printf(message, num, ( (num>1) ? "s" : "" ) );
3246: badflag = TRUE;
3247: }
3248: }
3249:
3250: chk(bn)
3251: register daddr_t bn;
3252: {
3253: if ( (bn<isize) || (bn>=fsize) ) {
3254: badflag = TRUE;
3255: if (++badcnt > MAXBADFREE)
3256: return( stopit("bad") );
3257: return(BAD);
3258: }
3259:
3260: if ( testdup(bn) ) {
3261: badflag = TRUE;
3262: if (++dupcnt > MAXDUPFREE)
3263: return( stopit("dup") );
3264: return(BAD);
3265: } else {
3266: markdup(bn);
3267: return(GOOD);
3268: }
3269: }
3270:
3271: stopit(type)
3272: char *type;
3273: {
3274: printf("Excessive %s blocks in free list ", type);
3275: if ( query("(Continue)") == YES )
3276: return(IGNORE);
3277: else
3278: return(ABORT);
3279: }
3280:
3281:
3282: canfblk(fbp)
3283: register struct fblk *fbp;
3284: {
3285: register short i;
3286:
3287: canshort(fbp->df_nfree);
3288: if ( (unsigned) fbp->df_nfree > NICFREE )
3289: return(FALSE);
3290:
3291: for (i=0; i<fbp->df_nfree; i++)
3292: candaddr(fbp->df_free[i]);
3293: return(TRUE);
3294: }
3295:
3296: asksalvage()
3297: {
3298: if ( (daction!=NO) && (qflag || sflag) ) {
3299: fixerup = TRUE;
3300: return;
3301: }
3302: if ( action("Bad Free List (SALVAGE)") )
3303: fixerup = TRUE;
3304: }
3305: @
3306:
3307:
3308: 1.1
3309: log
3310: @Initial revision
3311: @
3312: text
3313: @d26 1
3314: a26 1
3315: if (badflag)
3316: d62 5
3317: a66 1
3318: canfblk(fbp);
3319: d69 5
3320: a73 3
3321: /* printf("Total traversed free blocks = %U\n", total); */
3322: /* printf("Total free blocks by Superblock = %U\n", sbp->s_tfree); */
3323: /* printf("Running total free blocks = %U\n", totfree); */
3324: d146 3
3325: d151 2
3326: a153 2
3327: }
3328:
3329: d156 1
3330: a156 1
3331: if ( qflag && (daction!=NO) ) {
3332: @
3333: ( (daction!=NO) && (qflag || sflag) ) {
3334: fixerup = TRUE;
3335: return;
3336: }
3337: if ( action("Bad Free List (SALVAGE)") )
3338: fixerup = TRUE;
3339: }
3340: @
3341:
3342:
3343: 1.1
3344: log
3345: @Initial revision
3346: @
3347: text
3348: @d26 1
3349: a26 1
3350: if (badflag)
3351: d62 5
3352: afsck/RCS/phase6.c,v 444 3 3 5736 4771205312 7176 head 1.2;
3353: access ;
3354: symbols ;
3355: locks bin:1.2;
3356: comment @ * @;
3357:
3358:
3359: 1.2
3360: date 91.03.18.18.45.18; author bin; state Exp;
3361: branches ;
3362: next 1.1;
3363:
3364: 1.1
3365: date 91.02.05.16.38.52; author bin; state Exp;
3366: branches ;
3367: next ;
3368:
3369:
3370: desc
3371: @prov by epstein (post 310)
3372: @
3373:
3374:
3375: 1.2
3376: log
3377: @update provided by epstein.
3378: @
3379: text
3380: @/*
3381: * phase 6 of fsck - Salvage Free List
3382: */
3383:
3384: #include "fsck.h"
3385:
3386: static unsigned char *maptab; /* table of interleave offsets */
3387: static daddr_t mapbot; /* minimum block number to interleave map */
3388: static daddr_t maptop; /* maximum block number to interleave map */
3389: static short m,n; /* interleave factors */
3390: #define DEF_N 1 /* default values */
3391: #define DEF_M 1
3392: daddr_t freeblks; /* number free blocks left to write out */
3393: daddr_t blknm; /* current block number we are working with */
3394: struct fblk *fblkp; /* pointer to free block list */
3395: daddr_t *dp; /* pointer to block entry in free list block */
3396:
3397: phase6()
3398: {
3399: if (!fixerup) {
3400: return;
3401: }
3402:
3403: if (!qflag)
3404: printf("Phase 6 : Salvage Free List\n");
3405: if ( maketable() == BAD )
3406: return;
3407: writefree();
3408: free(maptab);
3409: }
3410:
3411: maketable()
3412: {
3413: register int i;
3414: register int ratio;
3415:
3416: m = sbp->s_m;
3417: n = sbp->s_n;
3418:
3419: if ( (n > MAXINTN) || (m > n) || (n%m != 0) ) {
3420: printf("Invalid interleave factors in superblock.\n");
3421: printf("Default free-block list spacing assumed.\n");
3422: sbp->s_n = n = DEF_N;
3423: sbp->s_m = m = DEF_M;
3424: }
3425:
3426: if ( (maptab = malloc(n)) == NULL ) {
3427: printf("Can't malloc space for interleave table.\n");
3428: printf("Free-block list is not rebuilt.\n");
3429: return(BAD);
3430: }
3431:
3432: mapbot = (isize + n - 1)/n*n;
3433: maptop = fsize/n*n;
3434: ratio = n/m;
3435: for (i=0; i<n; i++)
3436: maptab[i] = (i/ratio) + (i%ratio)*m;
3437:
3438: return(GOOD);
3439: }
3440:
3441: writefree()
3442: {
3443: register daddr_t bn;
3444: daddr_t blk, bmap();
3445: short num;
3446:
3447: sbpfix = TRUE;
3448: freeblks = totfree;
3449: blknm = SUPERI;
3450: fblkp = (struct fblk *) &sbp->s_nfree;
3451: fblkp->df_nfree = num = (freeblks < NICFREE) ? freeblks : NICFREE;
3452: freeblks -= num;
3453: dp = &fblkp->df_free[num];
3454: for (bn=isize; bn<fsize; bn++) {
3455: blk = bmap(bn);
3456: if ( !testblock(blk) )
3457: if ( addfree(blk) == STOP )
3458: break;
3459: }
3460: }
3461:
3462: addfree(bn)
3463: daddr_t bn;
3464: {
3465: short num;
3466:
3467: *--dp = bn;
3468: if (dp > &fblkp->df_free[0])
3469: return(OK);
3470:
3471: if ( blknm != SUPERI ) {
3472: canwfblk(fblkp);
3473: bwrite(blknm, databuf);
3474: }
3475:
3476: bclear(databuf, BSIZE);
3477: if (freeblks == 0) {
3478: bwrite(bn, databuf);
3479: return(STOP);
3480: }
3481: blknm = bn;
3482: fblkp = (struct fblk *) databuf;
3483: fblkp->df_nfree = num = (freeblks < NICFREE) ? freeblks : NICFREE;
3484: freeblks -= num;
3485: dp = &fblkp->df_free[num];
3486: return(OK);
3487: }
3488:
3489: daddr_t
3490: bmap(blk)
3491: register daddr_t blk;
3492: {
3493: short i;
3494:
3495: if ( (blk>=mapbot) && (blk<maptop) ) {
3496: i = blk%n;
3497: blk -= i;
3498: blk += maptab[i];
3499: }
3500: return(blk);
3501: }
3502:
3503: canwfblk(fbp)
3504: register struct fblk *fbp;
3505: {
3506: register short i;
3507:
3508: for (i=0; i<fbp->df_nfree; i++)
3509: candaddr(fbp->df_free[i]);
3510: canshort(fbp->df_nfree);
3511: }
3512: @
3513:
3514:
3515: 1.1
3516: log
3517: @Initial revision
3518: @
3519: text
3520: @d7 1
3521: a7 1
3522: static char *maptab; /* table of interleave offsets */
3523: d114 1
3524: a114 1
3525: int i;
3526: d117 3
3527: a119 2
3528: i = ((unsigned)blk)%n;
3529: blk += maptab[i] - i;
3530: @
3531: rn(OK);
3532: }
3533:
3534: daddr_t
3535: bmap(blk)
3536: regisfsck/RCS/printf.c,v 444 3 3 7620 4753557667 7333 head 1.1;
3537: access ;
3538: symbols ;
3539: locks ;
3540: comment @ * @;
3541:
3542:
3543: 1.1
3544: date 91.02.05.16.39.10; author bin; state Exp;
3545: branches ;
3546: next ;
3547:
3548:
3549: desc
3550: @prov by epstein (post310)
3551: @
3552:
3553:
3554:
3555: 1.1
3556: log
3557: @Initial revision
3558: @
3559: text
3560: @/*
3561: * Standard output printf using putchar.
3562: * Non-portable things:
3563: * 1) alignment of arguments is assumed to be completely contiguous.
3564: * 2) the smallest number is assumed to negate to itself.
3565: * 3) All of long, int, char*, and double are assumed to
3566: * be held in an exact number of ints.
3567: */
3568:
3569: #define NULL ((char *)0)
3570: #define putchar(c) { char b = c; write(1, &b, 1); }
3571: #include <sys/mdata.h>
3572:
3573: union alltypes {
3574: char c;
3575: int i;
3576: unsigned u;
3577: long l;
3578: double d;
3579: char *s;
3580: };
3581:
3582: #define bump(p,s) (p+=sizeof(s)/sizeof(int))
3583:
3584: char *printi();
3585: char *printl();
3586:
3587: static char null[] = "{NULL}";
3588:
3589: printf(args)
3590: union alltypes args;
3591: {
3592: xprintf(&args);
3593: }
3594: xprintf(argp)
3595: union alltypes *argp;
3596: {
3597: register char *cbp;
3598: int *iap;
3599: register c;
3600: char *s;
3601: char *cbs;
3602: char adj, pad;
3603: int prec;
3604: int fwidth;
3605: int pwidth;
3606: register char *fmt;
3607: union alltypes elem;
3608: char cbuf[64];
3609:
3610: iap = (int *)argp;
3611: fmt = *(char **)iap;
3612: bump(iap, char*);
3613: for (;;) {
3614: while((c = *fmt++) != '%') {
3615: if(c == '\0') {
3616: return;
3617: }
3618: putchar(c);
3619: }
3620: pad = ' ';
3621: fwidth = -1;
3622: prec = -1;
3623: c = *fmt++;
3624: if (c == '-') {
3625: adj = 1;
3626: c = *fmt++;
3627: } else
3628: adj = 0;
3629: if (c == '0') {
3630: pad = '0';
3631: c = *fmt++;
3632: }
3633: if (c == '*') {
3634: fwidth = *iap++;
3635: c = *fmt++;
3636: } else
3637: for (fwidth = 0; c>='0' && c<='9'; c = *fmt++)
3638: fwidth = fwidth*10 + c-'0';
3639: if (c == '.') {
3640: c = *fmt++;
3641: if (c == '*') {
3642: prec = *iap++;
3643: c = *fmt++;
3644: } else
3645: for (prec=0; c>='0' && c<='9'; c=*fmt++)
3646: prec = prec*10 + c-'0';
3647: }
3648: if (c == 'l') {
3649: c = *fmt++;
3650: if (c=='d' || c=='o' || c=='u' || c=='x')
3651: c += 'A' - 'a';
3652: }
3653: cbp = cbs = cbuf;
3654: switch (c) {
3655:
3656: case 'd':
3657: elem.i = *iap++;
3658: if (elem.i < 0) {
3659: elem.i = -elem.i;
3660: *cbp++ = '-';
3661: }
3662: cbp = printi(cbp, elem.i, 10);
3663: break;
3664:
3665: case 'u':
3666: cbp = printi(cbp, *iap++, 10);
3667: break;
3668:
3669: case 'o':
3670: cbp = printi(cbp, *iap++, 8);
3671: break;
3672:
3673: case 'x':
3674: cbp = printi(cbp, *iap++, 16);
3675: break;
3676:
3677: case 'D':
3678: elem.l = *(long *)iap;
3679: bump(iap, long);
3680: if (elem.l < 0) {
3681: elem.l = -elem.l;
3682: *cbp++ = '-';
3683: }
3684: cbp = printl(cbp, elem.l, 10);
3685: break;
3686:
3687: case 'U':
3688: cbp = printl(cbp, *(long *)iap, 10);
3689: bump(iap, long);
3690: break;
3691:
3692: case 'O':
3693: cbp = printl(cbp, *(long *)iap, 8);
3694: bump(iap, long);
3695: break;
3696:
3697: case 'X':
3698: cbp = printl(cbp, *(long *)iap, 16);
3699: bump(iap, long);
3700: break;
3701:
3702:
3703: case 's':
3704: if ((s = *(char **)iap) == NULL)
3705: s = null;
3706: bump(iap, char*);
3707: /*
3708: * Do %s specially so it can be longer.
3709: */
3710: cbp = cbs = s;
3711: while (*cbp++ != '\0')
3712: if (prec>=0 && cbp-s>prec)
3713: break;
3714: cbp--;
3715: break;
3716:
3717: case 'c':
3718: elem.c = *iap++;
3719: *cbp++ = elem.c;
3720: break;
3721:
3722: case 'r':
3723: xprintf(*(char ***)iap);
3724: bump(iap, char**);
3725: break;
3726:
3727: default:
3728: putchar(c);
3729: continue;
3730: }
3731: if ((pwidth = fwidth + cbs-cbp) < 0)
3732: pwidth = 0;
3733: if (!adj)
3734: while (pwidth-- != 0)
3735: putchar(pad);
3736: while (cbs < cbp)
3737: putchar(*cbs++);
3738: if (adj)
3739: while (pwidth-- != 0)
3740: putchar(pad);
3741: }
3742: }
3743:
3744: static char digits[] = {
3745: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
3746: 'A', 'B', 'C', 'D', 'E', 'F'
3747: };
3748:
3749: /*
3750: * Print an unsigned integer in base b.
3751: */
3752: static
3753: char *
3754: printi(cp, n, b)
3755: char *cp;
3756: register unsigned n;
3757: {
3758: register a;
3759: register char *ep;
3760: char pbuf[10];
3761:
3762: ep = &pbuf[10];
3763: *--ep = 0;
3764: for ( ; a = n/b; n=a)
3765: *--ep = digits[n%b];
3766: *--ep = digits[n];
3767: while (*ep)
3768: *cp++ = *ep++;
3769: return (cp);
3770: }
3771:
3772: /*
3773: * Print an unsigned long in base b.
3774: */
3775: static
3776: char *
3777: printl(cp, n, b)
3778: register char *cp;
3779: unsigned long n;
3780: register b;
3781: {
3782: char pbuf[13];
3783: unsigned long a;
3784: register char *ep;
3785:
3786: ep = &pbuf[13];
3787: *--ep = '\0';
3788: for ( ; (a = n/b) != 0; n = a)
3789: *--ep = digits[n%b];
3790: *--ep = digits[n];
3791: while (*ep)
3792: *cp++ = *ep++;
3793: return (cp);
3794: }
3795: @
3796: egister char *ep;
3797: char pbuf[10];
3798:
3799: ep = &pbuf[10];
3800: *--ep = 0;
3801: for ( ; a = n/b; n=a)
3802: *--ep = digits[n%b];
3803: *fsck/RCS/util.c,v 444 3 3 16442 5045006750 7001 head 1.2;
3804: branch ;
3805: access ;
3806: symbols ;
3807: locks bin:1.2;
3808: comment @ * @;
3809:
3810:
3811: 1.2
3812: date 91.07.29.07.45.21; author bin; state Exp;
3813: branches ;
3814: next 1.1;
3815:
3816: 1.1
3817: date 91.02.05.16.39.25; author bin; state Exp;
3818: branches ;
3819: next ;
3820:
3821:
3822: desc
3823: @prov by epstein (post 310)
3824: @
3825:
3826:
3827: 1.2
3828: log
3829: @Updated by epstein for version 321.
3830: @
3831: text
3832: @/*
3833: * general utility functions for phases of fsck
3834: */
3835:
3836: #include "fsck.h"
3837:
3838: struct stat stats; /* Used by statit() */
3839:
3840: statit(name, probfun)
3841: char *name;
3842: int (*probfun)();
3843: {
3844:
3845: if ( stat(name, &stats) == -1 ) {
3846: bclear(&stats, sizeof(struct stat));
3847: (*probfun)("Can not stat %s", name);
3848: }
3849: }
3850:
3851:
3852: query(x)
3853: {
3854: while(1) {
3855: printf("%r [yes/no]: ", &x);
3856:
3857: switch (daction) {
3858: case YES:
3859: printf("[default - YES]\n");
3860: return(YES);
3861: break;
3862: case NO:
3863: printf("[default - NO]\n");
3864: return(NO);
3865: break;
3866: case ASK:
3867: switch( nextchar() ) {
3868: case 'Y':
3869: return(YES);
3870: case 'N':
3871: return(NO);
3872: }
3873: }
3874: }
3875: }
3876:
3877: action(msg)
3878: char *msg;
3879: {
3880: switch( query(msg) ) {
3881: case YES:
3882: return(TRUE);
3883: case NO:
3884: return(FALSE);
3885: }
3886: }
3887:
3888: char
3889: nextchar()
3890: {
3891: char buff[8];
3892: int i, n, ch;
3893:
3894: if ( ((n=read(0,buff,8)) <= 0) || (n == 8) )
3895: fatal("Invalid Response");
3896:
3897: for(i=0; i<n; i++)
3898: if ( ((ch=buff[i])!=' ') && (ch!='\t') )
3899: break;
3900:
3901: if ( (ch>='a') && (ch<='z') )
3902: ch += 'A' - 'a';
3903:
3904: return(ch);
3905: }
3906:
3907: char *nfile = "FILE";
3908: char *ndir = "DIR";
3909: char *nchr = "Character Special";
3910: char *nblk = "Block Special";
3911: char *npipe = "PIPE";
3912: char *nunkwn = "Unknown I-node type";
3913:
3914: char *
3915: typename(ino)
3916: ino_t ino;
3917: {
3918: switch( flags(ino)&MODEMASK ) {
3919: case IREG:
3920: return(nfile);
3921: case IDIR:
3922: return(ndir);
3923: case ICHR:
3924: return(nchr);
3925: case IBLK:
3926: return(nblk);
3927: case IPIPE:
3928: return(npipe);
3929: default:
3930: return(nunkwn);
3931: }
3932: }
3933:
3934: abort()
3935: {
3936: fatal("abort.");
3937: }
3938:
3939: fatal(x)
3940: {
3941: printf("fsck: %r\n", &x);
3942: _exit(1);
3943: }
3944:
3945: nonfatal(x)
3946: {
3947: printf("fsck: %r\n", &x);
3948: errflag = TRUE;
3949: }
3950:
3951: /*
3952: * Inode Manipulation Routines
3953: * ptrino: returns a pointer to the wanted inode using the given
3954: * buffer to read in the block performing canonicalization.
3955: * writeino: writes the block containing the given inode to the
3956: * disk performing the necessary canonicalization
3957: * candino: canonicalize an inode
3958: *
3959: */
3960:
3961: struct dinode *
3962: ptrino(ino, buf)
3963: register ino_t ino;
3964: register char *buf;
3965: {
3966: register daddr_t bn;
3967: register struct dinode *dip;
3968:
3969: bn = iblockn(ino);
3970: if ( (testblock(bn)) && (bn!=INODEI) ) /* bad inode block */
3971: return(NULL);
3972: bread(bn, buf);
3973: dip = ((struct dinode *) buf) + iblocko(ino);
3974: candino(dip);
3975: return(dip);
3976: }
3977:
3978: writeino(ino, buf)
3979: ino_t ino;
3980: char *buf;
3981: {
3982: struct dinode *dip;
3983:
3984: dip = ((struct dinode *) buf) + iblocko(ino);
3985: candino(dip);
3986: bwrite((daddr_t) iblockn(ino), buf);
3987: }
3988:
3989: candino(dip)
3990: register struct dinode *dip;
3991: {
3992: canshort(dip->di_mode);
3993: canshort(dip->di_nlink);
3994: canshort(dip->di_uid);
3995: canshort(dip->di_gid);
3996: cansize(dip->di_size);
3997: cantime(dip->di_atime);
3998: cantime(dip->di_mtime);
3999: cantime(dip->di_ctime);
4000: }
4001:
4002: /*
4003: * Transfer a logical block number for an inode to a
4004: * physical block number, chasing indirects as necessary.
4005: * The inefficiency of this method is put up with since
4006: * this is only used for directory inodes, and they tend
4007: * not to use indirects. Pass in 'addrs' which is a pointer
4008: * to the 13 daddr_s in the inode, and the logical block
4009: * number you would like. (Stolen from dcheck.c)
4010: */
4011:
4012: static daddr_t ranges[] = {
4013: ND,
4014: ND + (daddr_t)NI*NBN,
4015: ND + (daddr_t)NI*NBN + (daddr_t)NII*NBN*NBN,
4016: ND + (daddr_t)NI*NBN + (daddr_t)NII*NBN*NBN + (daddr_t)NIII*NBN*NBN*NBN
4017: };
4018:
4019: static char index[] = {
4020: 0,
4021: ND,
4022: ND+NI,
4023: ND+NI+NII
4024: };
4025:
4026: static daddr_t coeff[] = {
4027: 1, (daddr_t)NBN, (daddr_t)NBN*NBN, (daddr_t)NBN*NBN*NBN
4028: };
4029:
4030: daddr_t
4031: imap(addrs, block)
4032: daddr_t *addrs;
4033: register daddr_t block;
4034: {
4035: int i;
4036: register daddr_t bpos;
4037: register daddr_t *bp;
4038: register daddr_t bn;
4039:
4040: for (i=0; i<4; i++)
4041: if (block < ranges[i]) {
4042: if (i != 0)
4043: block -= ranges[i-1];
4044: bpos = block/coeff[i];
4045: block %= coeff[i];
4046: bp = &addrs[(int)bpos + index[i]];
4047: if ( (bn=*bp) != 0 ) {
4048: /*
4049: * Map through indirects here
4050: */
4051: while (i-- > 0) {
4052: bread(bn, databuf);
4053: bpos = block/coeff[i];
4054: block %= coeff[i];
4055: bp = (daddr_t *)databuf + bpos;
4056: if ( (bn=*bp) == 0 )
4057: break;
4058: bn = *bp;
4059: candaddr(bn);
4060: }
4061: }
4062: return(bn);
4063: }
4064: return(0);
4065: }
4066:
4067: /*
4068: * Read the specified block number into the given buffer
4069: */
4070:
4071: char *rgblkerr = "Out of Range Block number: %U (CONTINUE)";
4072: char *skblkerr = "Can not Seek: Blk num: %U (CONTINUE)";
4073: char *rdblkerr = "Can not Read: Blk num: %U (CONTINUE)";
4074: char *wtblkerr = "Can not Write: Blk num: %U (CONTINUE)";
4075:
4076: bread(bn, buf)
4077: register daddr_t bn;
4078: register char *buf;
4079: {
4080: #ifdef DEBUG
4081: printf("Reading block number: %ld\n", bn);
4082: #endif
4083: if (bn<0 || bn >= fsize )
4084: switch( query(rgblkerr, bn) ) {
4085: case YES:
4086: bclear(buf, BSIZE);
4087: return;
4088: case NO:
4089: abort();
4090: }
4091:
4092: if ( (bn<isize) && getcache(bn, buf) ) {
4093: #if DEBUG
4094: bdump(buf);
4095: #endif
4096: return;
4097: }
4098:
4099: if ( lseek(fsfd, (unsigned long)bn*BSIZE, 0) == (-1L) )
4100: switch( query(skblkerr, bn) ) {
4101: case YES:
4102: bclear(buf, BSIZE);
4103: return;
4104: case NO:
4105: abort();
4106: }
4107:
4108: if ( read(fsfd, buf, BSIZE) != BSIZE )
4109: switch( query(rdblkerr, bn) ) {
4110: case YES:
4111: bclear(buf, BSIZE);
4112: return;
4113: case NO:
4114: abort();
4115: }
4116: #if DEBUG
4117: bdump(buf);
4118: #endif
4119: }
4120:
4121: /*
4122: * Write block number bn with data in buf
4123: */
4124:
4125: bwrite(bn, buf)
4126: daddr_t bn;
4127: char *buf;
4128: {
4129: #ifdef DEBUG
4130: printf("Writing block number: %ld\n", bn);
4131: #endif
4132: if (!writeflg)
4133: return;
4134:
4135: if (bn<0 || bn>=fsize)
4136: switch( query(rgblkerr, bn) ) {
4137: case YES:
4138: return;
4139: case NO:
4140: abort();
4141: }
4142:
4143: if ( lseek(fsfd, (fsize_t)BSIZE*bn, 0) == (-1L) )
4144: switch( query(skblkerr, bn) ) {
4145: case YES:
4146: return;
4147: case NO:
4148: abort();
4149: }
4150:
4151: if ( write(fsfd, buf, BSIZE) != BSIZE )
4152: switch( query(wtblkerr, bn) ) {
4153: case YES:
4154: return;
4155: case NO:
4156: abort();
4157: }
4158:
4159: if ( bn <= isize )
4160: chgcache(bn, buf);
4161: changeflg = TRUE;
4162: }
4163:
4164: /*
4165: * i-node block area caching routines
4166: */
4167:
4168: static char cache[NBLK * BSIZE];
4169: static int low = 0; high = -1;
4170:
4171: getcache(bn, buf)
4172: register daddr_t bn;
4173: register char *buf;
4174: {
4175: int totsize;
4176:
4177: if ( bn > isize )
4178: return(0);
4179:
4180: if ( (bn>=low) && (bn<=high) ) {
4181: blkmove(buf, &cache[BSIZE * (bn-low)]);
4182: return(1);
4183: }
4184:
4185: low = bn;
4186: if ( (high=bn+NBLK-1) > isize )
4187: high = isize;
4188: totsize = BSIZE * (high-low+1);
4189:
4190: if ( (lseek(fsfd, (unsigned long)bn*BSIZE, 0) == (-1L)) ||
4191: (read(fsfd, cache, totsize) != totsize) ) {
4192: low = 0; high = -1;
4193: return(0);
4194: }
4195:
4196: return( getcache(bn, buf) );
4197: }
4198:
4199: chgcache(bn, buf)
4200: register daddr_t bn;
4201: register char *buf;
4202: {
4203: if ( (bn>=low) && (bn<=high) )
4204: blkmove(&cache[BSIZE * (bn-low)], buf);
4205: }
4206:
4207: blkmove(to, from)
4208: register char *to, *from;
4209: {
4210: register int num=BSIZE;
4211:
4212: while ( num-- )
4213: *to++= *from++;
4214: }
4215:
4216: /*
4217: * Clear the given block of memory
4218: */
4219:
4220: bclear(bp, nb)
4221: register char *bp;
4222: register unsigned nb;
4223: {
4224: if (nb)
4225: do {
4226: *bp++ = 0;
4227: } while (--nb);
4228: }
4229:
4230:
4231: /*
4232: * Determine if the given block is bad
4233: */
4234:
4235: bad(bn)
4236: daddr_t bn;
4237: {
4238: if ( (bn >= isize) && (bn < fsize) )
4239: return(GOOD);
4240: else
4241: return(BAD);
4242: }
4243:
4244:
4245: #if DEBUG
4246:
4247: /*
4248: * Debug dump a block of data.
4249: */
4250:
4251: #define NUMPLIN 16
4252:
4253: bdump(buf)
4254: register unsigned char *buf;
4255: {
4256: register int i;
4257:
4258: for (i=0; i<BSIZE; i++) {
4259: if ( (i % NUMPLIN) == 0 )
4260: printf("\n0x%04x: ", i);
4261: printf(" %02x", *buf++);
4262: }
4263: printf("\n\n");
4264: }
4265:
4266: #endif
4267: @
4268:
4269:
4270: 1.1
4271: log
4272: @Initial revision
4273: @
4274: text
4275: @d261 4
4276: a264 1
4277: if ( (bn<isize) && getcache(bn, buf) )
4278: d266 1
4279: d285 3
4280: d412 24
4281: @
4282: iven block is bad
4283: */
4284:
4285: bad(bn)
4286: daddr_t bn;
4287: {
4288: if ( (bn >= isize) && (bn < fsize) )
4289: return(GOOD);
4290: else
4291: return(BAD);
4292: }
4293:
4294:
4295: #if DEBUG
4296:
4297: /*
4298: * Debug dump a block of data.
4299: */
4300:
4301: #define NUMPLIN 16
4302:
4303: bdump(buf)
4304: register unsignefsck/RCS/virtual.c,v 444 3 3 16557 4753557734 7543 head 1.1;
4305: access ;
4306: symbols ;
4307: locks ;
4308: comment @ * @;
4309:
4310:
4311: 1.1
4312: date 91.02.05.16.39.42; author bin; state Exp;
4313: branches ;
4314: next ;
4315:
4316:
4317: desc
4318: @prov by epstein (post 310)
4319: @
4320:
4321:
4322:
4323: 1.1
4324: log
4325: @Initial revision
4326: @
4327: text
4328: @/*
4329: * Virtual memory for fsck. Uses hash algorithm
4330: * rather than LRU to get it up fast.
4331: */
4332: #include <assert.h>
4333: #include <sys/stat.h>
4334: #include "fsck.h"
4335:
4336: #define VBLKB 9 /* bytes in virtual block as power of 2 */
4337: #define VBLK (1 << VBLKB) /* bytes in a virtual block */
4338: #define MBKSB 6 /* number of virtual blocks as power of 2 */
4339: #define MBKS (1 << MBKSB) /* number of virtual blocks */
4340:
4341: #define DVTMP "/dev/rram1" /* Default Virtual Temp Filename */
4342: #define DVTMPCLS "/dev/rram1close" /* Default Virtual Temp File Close */
4343: #define MAJORRAM 8 /* Major Device Number for the Ram Disk */
4344:
4345: struct mapper {
4346: unsigned dirty:1;
4347: unsigned what_in:15; /* which block is in memory */
4348: };
4349:
4350: static unsigned long flagdsp, blkdsp, dupdsp, duplim;
4351: static struct mapper map[MBKS];
4352: static unsigned char data[MBKS][VBLK];
4353: static int tmp;
4354:
4355: static char *dvtmp = DVTMP;
4356: static char *dvtmpcls = DVTMPCLS;
4357:
4358: /*
4359: * Init file system for virtual arrays.
4360: * Data is ordered links, flags, blocks then dups.
4361: */
4362: initV(links, flags, blocks, dups)
4363: unsigned links, flags, blocks, dups;
4364: {
4365: register long bp;
4366: struct stat st;
4367: unsigned datasiz;
4368:
4369: flagdsp = links;
4370: blkdsp = flagdsp + flags;
4371: dupdsp = blkdsp + blocks;
4372: duplim = dupdsp + dups;
4373:
4374: memset(map, 0, sizeof(map)); /* zero ram arrays */
4375: memset(data, 0, sizeof(data));
4376:
4377: tmp = -1;
4378:
4379: datasiz = sizeof(data);
4380: if ( duplim < datasiz )
4381: return;
4382:
4383: if ( tmpfile == NULL ) {
4384: switch ( is_fs(dvtmp) ) {
4385: case -1:
4386: fatal(
4387: "Can't access ram disk \"%s\", use the -t option", dvtmp);
4388: case 0:
4389: break;
4390: case 1:
4391: fatal(
4392: "Possible file system on ram disk \"%s\", use the -t option", dvtmp);
4393: }
4394: if ( (-1 == stat(dvtmp, &st)) || !(st.st_mode&S_IFCHR) ||
4395: (major(st.st_rdev) != MAJORRAM) )
4396: fatal("Ram disk \"%s\" not mknod'ed properly",
4397: dvtmp);
4398: if ( -1 == (tmp = open(dvtmp, 2)) )
4399: fatal("Cannot open read/write Ram Disk \"%s\"", dvtmp);
4400:
4401: /* Ram disk driver may not promise zeroed start.
4402: * This code may go later. Extra write not important. */
4403: for(bp = 0; bp < duplim; bp += VBLK) /* zero disk stuff */
4404: if ( VBLK != write(tmp, data[0], VBLK) )
4405: fatal("Error writing to tmp file");
4406: } else {
4407: if ( -1 == (tmp = open(tmpfile, 2)) ) {
4408: if ( -1 == (tmp = creat(tmpfile, 0600)) )
4409: fatal("Cannot create temp file \"%s\"",
4410: tmpfile);
4411: close(tmp);
4412: tmp = open(tmpfile, 2);
4413: unlink(tmpfile);
4414: }
4415: if ( -1 == fstat(tmp, &st) )
4416: fatal("Can't stat temp file \"%s\"", tmpfile);
4417: if ( st.st_dev == fsysrdev )
4418: fatal("Temp File must not be on file system to fsck");
4419: }
4420: }
4421:
4422: /*
4423: * cleanup virtual system
4424: */
4425: cleanV()
4426: {
4427: struct stat st;
4428:
4429: if ( tmp == -1 ) /* No Virtual Temp File Opened */
4430: return;
4431:
4432: close(tmp);
4433: if ( tmpfile != NULL ) /* Virtual File not Default RAMDisk */
4434: return;
4435: /* Virtual File is Default RAMDisk */
4436: if ( (-1 == stat(dvtmpcls, &st)) || !(st.st_mode&S_IFCHR) ||
4437: (major(st.st_rdev) != MAJORRAM) ||
4438: ((minor(st.st_rdev)&0x7F) != 0) )
4439: fatal("Ram disk close \"%s\" not mknod'ed properly", dvtmpcls);
4440: if ( -1 == (tmp = open(dvtmpcls, 2)) )
4441: fatal("Cannot open Ram Disk Close \"%s\"", dvtmpcls);
4442: if ( close(tmp) < 0 )
4443: fatal("Cannot close Ram Disk Close \"%s\"", dvtmpcls);
4444: }
4445:
4446: /*
4447: * All actions for virtual array
4448: */
4449: findblock(bp, action, odata)
4450: long bp; /* data address */
4451: enum vact action; /* what to do */
4452: unsigned odata; /* optional data */
4453: {
4454: unsigned which, what_in, byte_no, bit;
4455: unsigned long diskad;
4456: unsigned char *byte;
4457: extern long lseek();
4458:
4459: switch(action) { /* use displacment to correct part of file */
4460: case testBlock:
4461: case markBlock:
4462: case unmarkBlock:
4463: bit = 1 << (bp & 7);
4464: bp >>= 3;
4465: case grabBlock: /* 8 at a time for copy */
4466: assert(bp >= 0);
4467: bp += blkdsp;
4468: assert(bp < dupdsp);
4469: break;
4470: case testDup:
4471: case markDup:
4472: case unmarkDup:
4473: bit = 1 << (bp & 7);
4474: bp >>= 3;
4475: case setDup: /* 8 at a time for copy */
4476: assert(bp >= 0);
4477: bp += dupdsp;
4478: assert(bp < duplim);
4479: break;
4480: case Flags:
4481: case setFlags:
4482: case orFlags:
4483: assert(bp > 0);
4484: bp += flagdsp - 1;
4485: assert(bp < blkdsp);
4486: break;
4487: case linkCtr:
4488: case incLinkctr:
4489: case setLinkctr:
4490: assert(bp > 0);
4491: bp--;
4492: assert(bp < flagdsp);
4493: }
4494:
4495: byte_no = bp & (VBLK - 1);
4496: bp >>= VBLKB;
4497: which = bp & (MBKS - 1);
4498: bp >>= MBKSB;
4499: what_in = bp & 0x7fff;
4500:
4501: if((diskad = map[which].what_in) != what_in) {
4502: if(map[which].dirty) {
4503: diskad <<= VBLKB + MBKSB;
4504: diskad += which << VBLKB;
4505: if(-1 == lseek(tmp, diskad, 0))
4506: fatal("Error seeking tmp file");
4507: if(VBLK != write(tmp, data[which], VBLK))
4508: fatal("Error writing tmp file");
4509: }
4510: diskad = what_in;
4511: diskad <<= VBLKB + MBKSB;
4512: diskad += which << VBLKB;
4513: if(-1 == lseek(tmp, diskad, 0))
4514: fatal("Error seeking tmp file");
4515: if(VBLK != read(tmp, data[which], VBLK))
4516: memset(data[which], 0, VBLK);
4517: map[which].what_in = what_in;
4518: map[which].dirty = 0; /* clean */
4519: }
4520: byte = &data[which][byte_no];
4521:
4522: switch(action) {
4523: case testBlock:
4524: case testDup:
4525: return(*byte & bit);
4526: case markBlock:
4527: case markDup:
4528: map[which].dirty = 1;
4529: return(*byte |= bit);
4530: case unmarkBlock:
4531: case unmarkDup:
4532: map[which].dirty = 1;
4533: return(*byte ^= bit);
4534: case linkCtr:
4535: case Flags:
4536: case grabBlock:
4537: return(*byte);
4538: case setLinkctr:
4539: case setFlags:
4540: case setDup:
4541: map[which].dirty = 1;
4542: return(*byte = odata);
4543: case orFlags:
4544: map[which].dirty = 1;
4545: return(*byte |= odata);
4546: case incLinkctr:
4547: map[which].dirty = 1;
4548: return(++*byte);
4549: default:
4550: fatal("Bad action in virtual system");
4551: }
4552: }
4553:
4554: /*
4555: * copy virtual memory blockmap to dupmap
4556: * read and write groups to avoid possable thrashing.
4557: */
4558: void
4559: copyV(size)
4560: unsigned size;
4561: {
4562: char buf[128];
4563: register int i;
4564: long bp, bs;
4565:
4566: for(bs = bp = 0; bp < size; ) {
4567: for(i = 0; (i < 128) && (bp < size); i++, bp++)
4568: buf[i] = findblock(bp, grabBlock);
4569:
4570: for(i = 0; (i < 128) && (bs < size); i++, bs++)
4571: findblock(bs, setDup, buf[i]);
4572: }
4573: }
4574:
4575: #ifdef TEST
4576: fatal(s)
4577: char *s;
4578: {
4579: fprintf(stderr, "%s\n", s);
4580: exit(1);
4581: }
4582:
4583: static char buf[80];
4584: gbuf()
4585: {
4586: if(NULL == gets(buf)) {
4587: unlink("vtmp");
4588: exit(0);
4589: }
4590: return(buf[0]);
4591: }
4592:
4593: main()
4594: {
4595: unsigned long b;
4596: char data;
4597:
4598: initV(10000, 10000, 20000);
4599: for(;;) {
4600: printf("b = block, d = dup, f = flags, l = linkctr\n");
4601: switch(gbuf()) {
4602: case 'l':
4603: printf("s = set, d = display, i = increment: then loc\n");
4604: gbuf();
4605: sscanf(buf + 2, "%ld", &b);
4606: switch(buf[0]) {
4607: case 's':
4608: setlinkctr(b, 0); /* no data */
4609: case 'd':
4610: printf("%d\n", linkctr(b));
4611: break;
4612: case 'i':
4613: printf("%d\n", inclinkctr(b));
4614: }
4615: break;
4616: case 'f':
4617: printf("d = display, s = set, o = or: then loc\n");
4618: gbuf();
4619: sscanf(buf + 2, "%ld %c", &b, &data);
4620: switch(buf[0]) {
4621: case 's':
4622: setflags(b, data);
4623: case 'd':
4624: break;
4625: case 'o':
4626: orflags(b, data);
4627: }
4628: printf("%c\n", flags(b));
4629: break;
4630: case 'b':
4631: printf("t = test, m = mark, u = unmark: then loc\n");
4632: gbuf();
4633: sscanf(buf + 2, "%ld", &b);
4634: switch(buf[0]) {
4635: case 'm':
4636: markblock(b);
4637: case 't':
4638: break;
4639: case 'u':
4640: unmarkblock(b);
4641: }
4642: printf("%c\n", testblock(b) ? '1' : '0');
4643: break;
4644: case 'd':
4645: printf("t = test, m = mark, u = unmark: then loc\n");
4646: gbuf();
4647: sscanf(buf + 2, "%ld", &b);
4648: switch(buf[0]) {
4649: case 'm':
4650: markdup(b);
4651: case 't':
4652: break;
4653: case 'u':
4654: unmarkdup(b);
4655: }
4656: printf("%c\n", testdup(b) ? '1' : '0');
4657: break;
4658: }
4659: }
4660: }
4661: #endif
4662:
4663: @
4664: loc\n");
4665: gbuf();
4666: sscanf(buf + 2, "%ld", &b);
4667: switch(buf[0]) {
4668: case 'm':
4669: markblock(b);
4670: case 't':
4671: break;
4672: case 'u':
4673: ufsck/READ_ME 644 3 3 1227 4664524112 5766 Ideas for improving the performance of fsck:
4674:
4675: (1) Utilize a different mechanism for storing the (struct direct)
4676: entries throughout phase2.c, to remove implicit memory intensive
4677: redundancy.
4678:
4679: (2) Encode the number of links per i-node count differently, in order
4680: to save space taking advantage of the typical usage under Coherent.
4681:
4682: (3) Arrange space for the tables in a total needed way to avoid later
4683: fragmentation problems affecting the memory requests for successive
4684: file systems.
4685:
4686: (4) Devise a more clever buffering scheme for the blocks containing
4687: i-nodes to understand the differences between phase1, phase2, and
4688: phase4.
4689: emove implicit memory intensive
4690: redundancy.
4691:
4692: (2) Encode the number of links per i-node count differently, in order
4693: to save space taking advantage of the typical usage under Coherent.
4694:
4695: (3) Arrange space for the tables in a total needed way to avoid later
4696: fragmentation problems affecting the memory requests for successive
4697: file systems.
4698:
4699: (4fsck/cleanup.c 644 3 3 2324 4664524112 6541 /*
4700: * Cleanup functions for phases of fsck
4701: */
4702:
4703: #include "fsck.h"
4704:
4705: cleanup()
4706: {
4707: int retval = 0;
4708:
4709: if (sbpfix == TRUE)
4710: writesuper();
4711: prtstats();
4712: if (changeflg == TRUE)
4713: retval = advise();
4714: close(fsfd);
4715: cleanV();
4716: return(retval);
4717: }
4718:
4719: writesuper()
4720: {
4721: register int i;
4722:
4723: canshort(sbp->s_isize);
4724: candaddr(sbp->s_fsize);
4725: canshort(sbp->s_nfree);
4726: for(i=0; i<NICFREE; i++)
4727: candaddr(sbp->s_free[i]);
4728: canshort(sbp->s_ninode);
4729: for(i=0; i<NICINOD; i++)
4730: canino(sbp->s_inode[i]);
4731: cantime(sbp->s_time);
4732: candaddr(sbp->s_tfree);
4733: canino(sbp->s_tinode);
4734: canshort(sbp->s_m);
4735: canshort(sbp->s_n);
4736: canlong(sbp->s_unique);
4737:
4738: bwrite((daddr_t)SUPERI, sbp);
4739: }
4740:
4741: prtstats()
4742: {
4743: if (!fflag)
4744: printf("%u files ", numfiles);
4745: printf("%U blocks ", fsize - isize - totfree);
4746: printf("%U free\n", totfree);
4747: if ( lostsize ) {
4748: lostsize = (lostsize + BSIZE - 1)/BSIZE;
4749: printf("Expect roughly %U missing block%s next\n", lostsize,
4750: (lostsize!=1) ? "s" : "" );
4751: printf("time fsck is run as a result of inodes ");
4752: printf("being cleared.\n");
4753: }
4754: }
4755:
4756: advise()
4757: {
4758: int retval = 0;
4759:
4760: printf(" ***** File System %s was modified *****\n", fsname);
4761: if ( mounted ) {
4762: printf(" ***** BOOT Coherent (NO SYNC!) *****\n");
4763: retval = 1;
4764: }
4765: return(retval);
4766: }
4767: blocks ", fsize - isize - totfree);
4768: printf("%U free\n", totfree);
4769: if ( lostsize ) {
4770: lostsize = (lostsize + BSIZE - 1)/BSIZE;
4771: printf("Expect roughly %U missing block%s next\n", lostsize,
4772: (lostsize!=1) ? "s" : "" );
4773: printf("time fsck is run as a result of inodes ");
4774: printf("being clearedfsck/fsck.h 644 3 3 14003 5033723044 6056 /*
4775: * Header file for fsck -- File System Check Program
4776: *
4777: */
4778:
4779: #include <canon.h>
4780: #include <sys/dir.h>
4781: #include <sys/fblk.h>
4782: #include <sys/filsys.h>
4783: #include <sys/ino.h>
4784: #include <sys/stat.h>
4785: #include <sys/types.h>
4786: #include <time.h>
4787:
4788: #if HPCOHERENT
4789: typedef long fsize_t;
4790: #endif
4791:
4792: /*
4793: * Conditional Compilation Flags
4794: */
4795:
4796: #define NOT_ALL_ZERO_INODE /* Dependent on whether or not an inode */
4797: #ifdef ALL_ZERO_INODE /* is totally zeroed when unallocated */
4798: #undef ALL_ZERO_INODE /* or simply a zero mode and zero link */
4799: #endif
4800:
4801:
4802: /*
4803: * Definitions and Externs
4804: */
4805:
4806: #define NUL 0 /* true zero ! */
4807: #define NULL ((char *)0)
4808:
4809: #define YES 3 /* default actions */
4810: #define NO 2
4811: #define ASK 1
4812:
4813: #define NFILSYS 10 /* max number of file systems */
4814: #define MAXCH 20 /* max length of filesys name */
4815:
4816: #define MAXBADOK 10 /* Max number of bad blocks before excessive */
4817: extern int numbad; /* num bad blocks found so far this inode*/
4818:
4819: #define MAXDUPOK 10 /* Max number of dup blocks */
4820: /* in a single inode before excessive */
4821: #define DUPTBLSIZE 20 /* Max number of dup referenced blocks */
4822: extern daddr_t dupblck[]; /* table of duplicate referenced blocks */
4823: extern int totdups; /* number of dup blocks found so far */
4824:
4825: #define MAXBADFREE 10 /* max bad in free list before abort */
4826: #define MAXDUPFREE 10 /* max dup in free list before abort */
4827:
4828: #define GOOD 1 /* returned by bad() in util.c */
4829: #define BAD 0
4830:
4831: #define TRUE 1 /* errflag possibilities */
4832: #define FALSE 0
4833: extern int errflag; /* errflag indicates not to do phases */
4834:
4835: #define OK 1 /* used to indicate excessive bad/dup */
4836: #define STOP 0 /* blocks in an inode in phase1.c */
4837: #define BAD_DUP 2
4838:
4839: #define FIRSTIN 2 /* First real inode number */
4840:
4841: #define ND 10 /* Number of Direct Blocks */
4842: #undef NI
4843: #define NI 1
4844: #define NII 1
4845: #define NIII 1
4846: #undef NADDR
4847: #define NADDR (ND+NI+NII+NIII)
4848: extern int offsets[]; /* table of offsets for level of indirection */
4849: /* for the blocks in an inode */
4850:
4851: extern char nextchar(); /* used in util.c */
4852: extern int fsfd; /* file system file descriptor */
4853: extern int mdaction; /* default action for this invocation */
4854: extern int daction; /* default action for current file system */
4855: extern int writeflg; /* system write ok or read-only */
4856: extern int qflag; /* quiet fsck flag */
4857: extern int fflag; /* fast fsck flag */
4858: extern int sflag; /* force free list salvation */
4859: extern daddr_t fsize; /* file system size in blocks */
4860: extern int isize; /* first block not in inode list */
4861: /* isize is NOT unsigned so that comparisons */
4862: /* with longs will not cast the long to */
4863: /* unsigned thus producing confusing results */
4864:
4865: extern daddr_t totfree; /* running count of total free blocks */
4866: extern unsigned ninodes;/* Number of inodes in the files system */
4867: extern char *fsname; /* file system name */
4868: extern fsize_t pinfo(); /* returns size of file, in phase2.c */
4869: extern ino_t lostfound(); /* returns inumber of lost+found dir */
4870: extern struct dinode *ptrino(); /* returns a ptr to inode, give number */
4871: extern char databuf[]; /* buffer to read in block, used throughout */
4872: extern char buf2[]; /* alternate data buffer */
4873: extern daddr_t cdbn; /* current block number, used by nextblock() */
4874: #define DSIZE (sizeof(struct direct))
4875: extern char *lostname; /* name of lost+found directory */
4876: extern char *nameit(); /* nameing function for lost dirs and files */
4877: extern int depth; /* used during tree traversal in phase2.c */
4878: extern struct direct *path[]; /* used during tree traversal in phase2.c */
4879: extern char *typename(); /* return string to type of inode */
4880: extern struct filsys *sbp; /* Super Block */
4881: extern int sbpfix; /* flag for super block fixes */
4882: extern struct stat stats; /* used by statit() in util.c */
4883: extern dev_t rootdev; /* root device number */
4884: extern dev_t fsysrdev; /* file system real device number */
4885: extern int mounted; /* flag indicating mountedness of filesystem */
4886: extern int changeflg; /* file system modified flag */
4887: extern int fixerup; /* flag to rebuild free list */
4888: extern char *fixit; /* Prompt message phase[45].c */
4889: extern int numfiles; /* num files in system */
4890: extern daddr_t imap(); /* function for disk block mapping in util.c */
4891: extern fsize_t lostsize; /* Size of files cleared in phase4.c */
4892: extern char *tmpfile; /* TMP File name for virtual.c */
4893:
4894: #define SUCCESS 1 /* used in connect() in phase3.c */
4895: #define FAILURE 0
4896:
4897: #define MODEMASK 0x07
4898: #define ALLOCMASK 0x06
4899: #define UNALLOC 0x00
4900: #define UNKNOWN 0x01
4901: #define IDIR 0x02
4902: #define IREG 0x03
4903: #define ICHR 0x04
4904: #define IBLK 0x05
4905: #define IPIPE 0x06
4906: #define IBAD_IDUP 0x08
4907: #define VISITED 0x10
4908: #define UNREFDIR 0x20
4909: #define CHILDDIR 0x40
4910: #define IFREELIST 0x80
4911:
4912: /*
4913: * Macros for tables
4914: */
4915:
4916: #define LOGNBPC 3 /* Log2 Number of Bits per Character */
4917:
4918: /* Actions for virtual block system */
4919: enum vact { testBlock, markBlock, unmarkBlock, grabBlock,
4920: testDup, markDup, unmarkDup, setDup,
4921: Flags, setFlags, orFlags,
4922: linkCtr, incLinkctr, setLinkctr };
4923:
4924: #define testblock(bn) findblock((unsigned long)(bn), testBlock)
4925: #define markblock(bn) findblock((unsigned long)(bn), markBlock)
4926: #define unmarkblock(bn) findblock((unsigned long)(bn), unmarkBlock)
4927:
4928: #define testdup(bn) findblock((unsigned long)(bn), testDup)
4929: #define markdup(bn) findblock((unsigned long)(bn), markDup)
4930: #define unmarkdup(bn) findblock((unsigned long)(bn), unmarkDup)
4931:
4932: #define flags(ino) findblock((unsigned long)(ino), Flags)
4933: #define setflags(ino, data) findblock((unsigned long)(ino), setFlags, data)
4934: #define orflags(ino, data) findblock((unsigned long)(ino), orFlags, data)
4935:
4936: #define linkctr(ino) findblock((unsigned long)(ino), linkCtr)
4937: #define inclinkctr(ino) findblock((unsigned long)(ino), incLinkctr)
4938: #define setlinkctr(ino, data) findblock((unsigned long)(ino), setLinkctr, data)
4939:
4940: #define badblks(ino) ( flags(ino)&IBAD_IDUP )
4941:
4942: /*
4943: * Miscellany
4944: */
4945:
4946: #define NBPC 8 /* number of bits per character */
4947: #define MAXINTN 255 /* used for interleave table */
4948: /* in phase6.c */
4949: /*
4950: * Stdio Stuff
4951: */
4952:
4953: #define putchar(c) { char b = c; write(1, &b, 1); }
4954: extern char *malloc();
4955: extern char *calloc();
4956:
4957: findblock((unsigned long)(ino), linkCtr)
4958: #define inclinkctr(ino) findblock((unsigned long)(ino), incLinkctr)
4959: #define setlinkctr(ino, data) findblock((unsigned long)(ino), setLinkctr, data)
4960:
4961: #define badblks(ino) ( flags(ino)&IBAD_IDUP )
4962:
4963: /*
4964: * Miscellany
4965: */
4966:
4967: #define NBPC 8 /* number of bits per character */
4968: #define MAXINTN 255 /* used for interleave table */
4969: /* in phase6.c */
4970: /*
4971: * Stdio Stuff
4972: */
4973:
4974: #define putchar(c) { char b = c; write(1, &b, 1); }
4975: extern char *malloc();
4976: extern char *calloc()fsck/init.c 644 3 3 12651 5041132573 6075 /*
4977: * Perform initialization for phases of fsck
4978: */
4979: #include "fsck.h"
4980: #include <mnttab.h>
4981: #include <mtab.h>
4982:
4983: int fsfd; /* file system file descriptor */
4984: int writeflg; /* write ok or read-only flag */
4985: daddr_t fsize = SUPERI+1; /* file system size in blocks */
4986: /* Allows for read of Super Block */
4987: int isize; /* First block not in inode list */
4988: daddr_t totfree; /* Running total free block count */
4989: unsigned ninodes; /* number of inodes */
4990: int numfiles; /* number of files in file system */
4991:
4992: char superb[BSIZE]; /* Super Block */
4993: struct filsys *sbp = superb;
4994: int sbpfix; /* flag for super block fixes */
4995:
4996: int offsets[] = /* table of offsets for the levels */
4997: { ND, ND+NI, ND+NI+NII, /* of indirection of blocks in the */
4998: ND+NI+NII+NIII }; /* inode block list */
4999:
5000: daddr_t dupblck[DUPTBLSIZE]; /* duplicate referenced blocks */
5001: int totdups; /* number of dup blocks so far */
5002:
5003: init()
5004: {
5005: int mode;
5006: struct stat status;
5007: unsigned short stmode;
5008:
5009: mode = (mdaction == NO) ? 0 : 2;
5010:
5011: if ( (fsfd = open(fsname, mode)) == (-1) ) {
5012: mode = 0;
5013: if ( (fsfd = open(fsname, mode)) == (-1) ) {
5014: nonfatal("Can't open: %s", fsname);
5015: return;
5016: }
5017: }
5018:
5019: if (mode == 0) {
5020: daction = NO;
5021: writeflg = FALSE;
5022: } else {
5023: daction = mdaction;
5024: writeflg = TRUE;
5025: }
5026:
5027: printf("%s: %s\n", fsname, (mode == 0) ? "(NO WRITE)" : "");
5028:
5029: if ( fstat(fsfd, &status) == (-1) ) {
5030: nonfatal("Can't stat: %s", fsname);
5031: return;
5032: }
5033:
5034: stmode = status.st_mode & S_IFMT;
5035: if ( (stmode != S_IFBLK) && (stmode != S_IFCHR) )
5036: switch(query("file is not a block or character device; OK?")){
5037: case YES:
5038: break;
5039: case NO:
5040: errflag = TRUE;
5041: return;
5042: }
5043:
5044: domount();
5045: sbpfix = FALSE;
5046: readsuper();
5047: checksuper();
5048: if ( !errflag )
5049: alloctables();
5050: }
5051:
5052: /*
5053: * Read in the super block and canonicalize
5054: */
5055:
5056: readsuper()
5057: {
5058: register int i;
5059:
5060: bread((daddr_t)SUPERI, superb);
5061: sbp = superb;
5062:
5063: canshort(sbp->s_isize);
5064: candaddr(sbp->s_fsize);
5065: canshort(sbp->s_nfree);
5066: for(i=0; i<NICFREE; i++)
5067: candaddr(sbp->s_free[i]);
5068: canshort(sbp->s_ninode);
5069: for(i=0; i<NICINOD; i++)
5070: canino(sbp->s_inode[i]);
5071: cantime(sbp->s_time);
5072: candaddr(sbp->s_tfree);
5073: canino(sbp->s_tinode);
5074: canshort(sbp->s_m);
5075: canshort(sbp->s_n);
5076: canlong(sbp->s_unique);
5077:
5078: }
5079:
5080: /*
5081: * Check super block for obvious inconsistencies
5082: */
5083:
5084: checksuper()
5085: {
5086: fsize = sbp->s_fsize;
5087: isize = sbp->s_isize;
5088: totfree = fsize - isize;
5089:
5090: if ( (isize<=INODEI) || (isize>=fsize) || (fsize<=INODEI) ) {
5091: badsuper("Size check: fsize %U isize %u", fsize, isize);
5092: errflag = TRUE;
5093: }
5094:
5095: if ( sbp->s_nfree > NICFREE )
5096: badsuper("Too large free block count");
5097:
5098: if ( sbp->s_ninode > NICINOD )
5099: badsuper("Too large free i-node count");
5100: }
5101:
5102: /*
5103: * Super Block Error Functions
5104: */
5105:
5106: badsuper(x)
5107: {
5108: printf("%r\n", &x);
5109: printf("fsck: %s: Bad Super Block: %u\n", fsname, SUPERI);
5110: }
5111:
5112: /*
5113: * Allocate the necessary buffers for tables
5114: */
5115:
5116: alloctables()
5117: {
5118: unsigned num, numl;
5119:
5120: numl = 0;
5121: if (!fflag) {
5122: ninodes = (unsigned) (isize - INODEI) * INOPB;
5123: numl = (unsigned) ninodes;
5124: }
5125:
5126: num = (unsigned) ((fsize+NBPC-1)/NBPC) * sizeof(char);
5127: initV(numl, numl, num, num); /* virtual allocation */
5128:
5129: numfiles = /* number of files in the file system */
5130: totdups = 0; /* num dup blocks */
5131: }
5132:
5133: /*
5134: * domount() checks the files /etc/mnttab and /etc/mtab to find
5135: * out where the file system is mounted (if at all). It then
5136: * reports where (and when if possible) it was last mounted.
5137: */
5138: char *mnttab_name = "/etc/mnttab";
5139: char *mtab_name = "/etc/mtab";
5140: char *bttime_name = "/etc/boottime";
5141:
5142: domount()
5143: {
5144: int fd;
5145: struct mnttab mnttab;
5146: struct mtab mtab;
5147: register char *name;
5148: struct stat sbuf;
5149: time_t boottime;
5150: int nothing();
5151: char devname[MNTNSIZ+6] = "/dev/";
5152:
5153: mounted = FALSE;
5154: name = fsname; /* strip off all initial */
5155: while (*name++ != '\0') ; /* directories in fsname */
5156: while ( (*--name != '/') && (name>fsname) ) ;
5157: if (*name == '/') name++;
5158:
5159: if ( stat(bttime_name, &sbuf) == -1 )
5160: boottime = (time_t)0;
5161: else
5162: boottime = sbuf.st_mtime;
5163:
5164: if ( (fd=open(mnttab_name, 0)) != (-1) ) {
5165: while ( read(fd, &mnttab, sizeof(mnttab))==sizeof(mnttab) )
5166: if ( mnttab.mt_dev[0] && mnttab.mt_filsys[0] ) {
5167: strncpy(&devname[5], mnttab.mt_filsys, MNTNSIZ);
5168: devname[MNTNSIZ+5] = '\0';
5169: statit(devname, nothing);
5170: if (stats.st_rdev != fsysrdev)
5171: continue;
5172: statit(mnttab.mt_dev, nothing);
5173: mounted = (stats.st_dev == fsysrdev);
5174: prmnttab(&mnttab, boottime);
5175: return;
5176: }
5177: }
5178: if ( (fd=open(mtab_name, 0)) != (-1) ) {
5179: while ( read(fd, &mtab, sizeof(mtab))==sizeof(mtab) )
5180: if ( mtab.mt_name[0] && mtab.mt_special[0] ) {
5181: strncpy(&devname[5], mtab.mt_special, MNAMSIZ);
5182: devname[MNAMSIZ+5] = '\0';
5183: statit(devname, nothing);
5184: if (stats.st_rdev != fsysrdev)
5185: continue;
5186: statit(mtab.mt_name, nothing);
5187: mounted = (stats.st_dev == fsysrdev);
5188: prmtab(&mtab);
5189: return;
5190: }
5191: }
5192:
5193: if (fsysrdev == rootdev)
5194: mounted = TRUE;
5195: else
5196: mounted = FALSE;
5197:
5198: }
5199:
5200: prmnttab(ptr, boottime)
5201: struct mnttab *ptr;
5202: time_t boottime;
5203: {
5204: if (mounted) {
5205: if (boottime < ptr->mt_time)
5206: boottime = ptr->mt_time;
5207: printf("%s mounted on %.*s as of %s", fsname, MNTNSIZ,
5208: ptr->mt_dev, ctime(&boottime));
5209: } else
5210: printf("%s unmounted. Last mounted on %.*s -- %s",
5211: fsname, MNTNSIZ, ptr->mt_dev,
5212: ctime(&ptr->mt_time));
5213: }
5214:
5215:
5216: prmtab(ptr)
5217: struct mtab *ptr;
5218: {
5219: if (mounted)
5220: printf("%s mounted on %.*s\n", fsname, MNAMSIZ, ptr->mt_name);
5221: else
5222: printf("%s unmounted. Last mounted on %.*s\n", fsname,
5223: MNAMSIZ, ptr->mt_name);
5224: }
5225:
5226: nothing()
5227: {}
5228: ) {
5229: if (boottime < ptr->mt_time)
5230: boottime = ptr->mt_time;
5231: printf("%s mounted on fsck/is_fs.c 644 3 3 3467 4705135657 6236 #include <sys/stat.h>
5232: #include <canon.h>
5233: #include <sys/filsys.h>
5234:
5235: /*
5236: * Check if a special file is a well-formed filesystem.
5237: * This routine is derived from code in "mount.c".
5238: * Return values:
5239: * -1 Not a device, cannot open, read or seek failed
5240: * 0 No filesystem
5241: * 1 Legal filesystem
5242: */
5243: int
5244: is_fs(special) char *special;
5245: {
5246: static struct filsys f;
5247: struct stat sbuf;
5248: register int fd;
5249: register struct filsys *fp;
5250: register daddr_t *dp;
5251: register ino_t *ip, maxinode;
5252:
5253: if (stat(special, &sbuf) < 0)
5254: return -1; /* cannot stat device */
5255: else if ((sbuf.st_mode&S_IFMT) != S_IFBLK
5256: && (sbuf.st_mode&S_IFMT) != S_IFCHR)
5257: return -1; /* not a special file */
5258: else if ((fd = open(special, 2)) < 0)
5259: return -1; /* cannot open */
5260: else if (lseek(fd, (long)SUPERI*BSIZE, 0) == -1L
5261: || read(fd, &f, sizeof(f)) != sizeof(f)) {
5262: close(fd);
5263: return -1; /* seek or read failed */
5264: } else
5265: close(fd); /* so far so good */
5266:
5267: /* Canonical stuff. */
5268: fp = &f;
5269: canshort(fp->s_isize);
5270: candaddr(fp->s_fsize);
5271: canshort(fp->s_nfree);
5272: for (dp = &fp->s_free[0]; dp < &fp->s_free[NICFREE]; dp += 1)
5273: candaddr(*dp);
5274: canshort(fp->s_ninode);
5275: for (ip = &fp->s_inode[0]; ip < &fp->s_inode[NICINOD]; ip += 1)
5276: canino(*ip);
5277: candaddr(fp->s_tfree);
5278: canino(fp->s_tinode);
5279:
5280: /* Test for rationality. */
5281: maxinode = (fp->s_isize - INODEI) * INOPB + 1;
5282: if (fp->s_isize >= fp->s_fsize)
5283: return 0;
5284: if ((fp->s_tfree < fp->s_nfree)
5285: || (fp->s_tfree >= fp->s_fsize - fp->s_isize + 1))
5286: return 0;
5287: if ((fp->s_tinode < fp->s_ninode) || (fp->s_tinode >= maxinode-1 ))
5288: return 0;
5289: for (dp = &fp->s_free[0]; dp < &fp->s_free[fp->s_nfree]; dp += 1)
5290: if ((*dp < fp->s_isize) || (*dp >= fp->s_fsize))
5291: return 0;
5292: for (ip = &fp->s_inode[0]; ip < &fp->s_inode[fp->s_ninode]; ip += 1)
5293: if ((*ip < 1) || (*ip > maxinode))
5294: return 0;
5295: return 1;
5296: }
5297: - INODEI) * INOPB + 1;
5298: if (fp->s_isize >= fp->s_fsize)
5299: return 0;
5300: if ((fp->s_tfree < fp->s_nfree)
5301: || (fp->s_tfree >= fp->s_fsize - fp->s_isize + 1))
5302: return 0;
5303: if ((fp->s_tinode < fp->s_ninode)fsck/link.c 644 3 3 2762 4664524116 6061 /*
5304: * Routines to handle the counting of links for each i-node
5305: */
5306:
5307: #include "fsck.h"
5308:
5309: linkincr(inum)
5310: ino_t inum;
5311: {
5312: if (inclinkctr(inum) == 0 )
5313: fatal("Too many links in i-node, %d", inum);
5314: }
5315:
5316: /*
5317: * The following is the beginning of thinking of how to change
5318: * the number of bits used in the link count tables from 8-per
5319: * i-node to 2-per i-node, with additional tables for those
5320: * i-nodes with more than 2 links. The changes would be to the
5321: * definition of i_lnks, the macro linkctr(), the function linkincr(),
5322: * and in init.c, the allocation of table space.
5323: */
5324:
5325: #ifdef NEWLINKSTUFFF
5326:
5327: char *linkmap; /* table of inodes with one link */
5328:
5329: #define testlink(in) ( linkmap[((unsigned)bn)>>(LOGNBPC-1)] & \
5330: 3 << (((unsigned)bn)&(NBPC>>1)) )
5331: #define marklink(in) ( linkmap[((unsigned)bn)>>(LOGNBPC-1)] |= \
5332: 1 << (((unsigned)bn)&(NBPC-2)) )
5333: #define unmarklink(in) ( linkmap[((unsigned)bn)>>(LOGNBPC-1)] ^= \
5334: 1 << (((unsigned)bn)&(NBPC-2)) )
5335:
5336: linkcntr(inum)
5337: ino_t inum;
5338: {
5339: index = ((unsigned) inum) >> (LOGNBPC-1) ;
5340: distance = ((unsigned) inum) & ((NBPC>>1) - 1) ;
5341: mask = 3 << distance;
5342: answer = ( linkmap[index] & mask ) >> distance;
5343:
5344: if ( answer < 3 )
5345: return(answer);
5346:
5347: hash = inum & 0xFF;
5348: bucket = &linktable[hash];
5349: bktinum = bucket->inumb;
5350:
5351: if ( bktinum == inum ) {
5352: answer = bucket->numlink;
5353: if ( answer == 0xFF )
5354: return( bigcntr(inum) );
5355: else
5356: return( answer + 3 );
5357: }
5358:
5359: if ( bktinum > inum )
5360: fatal("internal linktable corruption.");
5361:
5362:
5363: }
5364:
5365: linkincr(inum)
5366: ino_t inum;
5367: {
5368: }
5369:
5370: #endif
5371: num) >> (LOGNBfsck/main.c 644 3 3 12436 5041134504 6053 /*
5372: * fsck -- File System Check Program
5373: * an interactive file system check and repair program.
5374: *
5375: * Usage:
5376: * /etc/fsck [-y] [-n] [-q] [-f] [-{sS}] [-t TMPFILE] [filesystem ...]
5377: * audit and interactively repair inconsistent conditions for
5378: * file systems. Options -y and -n indicate an assumed response
5379: * to all questions asked by fsck. Default is to prompt operator
5380: * for yes/no response. Option -q is to quiet fsck from printing
5381: * certain messages, i.e. no size check messages, unreferenced
5382: * pipes will be silently removed, and counts in the superblock
5383: * will be automatically fixed and free list salvaged, if necessary.
5384: * Option -f is for a 'fast' check of the file system, i.e. only
5385: * check blocks, sizes, superblock counts, and the free list.
5386: * (-f) does not check pathnames, connectivity, or reference
5387: * counts. Option -s forces the reconstruction (or salvaging) of
5388: * both the free inode list and the free block list, even if there
5389: * are no file system problems. This will reorder the free block
5390: * list in the best order to limit additional fragmentation (respecting
5391: * interleaving as well). Note: Option -s will be ignored on mounted
5392: * file systems. The option -S acts in the same manner as -s except
5393: * that it will not be ignored on mounted file systems. Beware: -S
5394: * on mounted file systems should only be used if you intend to reboot
5395: * NO SYNC immediately afterwards. Option -t sets the temporary file
5396: * to use for disk caching of necessary tables on filesystems which are
5397: * too big to do in core. The temporary file defaults to "/dev/rram1",
5398: * which must be there.
5399: */
5400:
5401: #include "fsck.h"
5402:
5403: int errflag;
5404:
5405: int mdaction; /* default action for invocation */
5406: int daction; /* default action for file system */
5407: int gSflag=FALSE; /* force salvage flag ignored mounted */
5408: int gsflag=FALSE; /* force salvage flag ignored mounted */
5409: int sflag=FALSE; /* force salvage flag */
5410: int qflag=FALSE; /* fsck quiet flag */
5411: int fflag=FALSE; /* fsck fast flag */
5412:
5413: char *tmpfile = NULL; /* TMP file for virtual.c */
5414: char *checklistfile = "/etc/checklist"; /* default file for list of file */
5415: /* systems to fsck. */
5416: char *filelist[NFILSYS]; /* list of filesystems */
5417: char word[MAXCH]; /* hold single words */
5418: char *fsname; /* file system name */
5419:
5420: dev_t rootdev; /* root device number */
5421: dev_t fsysrdev; /* file system real device number */
5422: int mounted; /* flag for mounted file system */
5423:
5424: int changeflg; /* file system modified flag */
5425:
5426: main(argc, argv)
5427: char *argv[];
5428: {
5429: int yflag=0, nflag=0;
5430: int retval;
5431:
5432: while (argc>1 && *argv[1]=='-') {
5433: switch (argv[1][1]) {
5434: case 'q':
5435: qflag = TRUE;
5436: break;
5437: case 'y':
5438: yflag = 1;
5439: break;
5440: case 'n':
5441: nflag = 1;
5442: break;
5443: case 'f':
5444: fflag = TRUE;
5445: break;
5446: case 'S':
5447: gSflag = TRUE;
5448: break;
5449: case 's':
5450: gsflag = TRUE;
5451: break;
5452: case 't':
5453: tmpfile = argv[2];
5454: argc--;
5455: argv++;
5456: break;
5457: default:
5458: usage();
5459: break;
5460: }
5461:
5462: argc--;
5463: argv++;
5464: }
5465:
5466: if ( yflag+nflag > 1 )
5467: usage();
5468:
5469: mdaction = ( yflag ? YES :
5470: nflag ? NO : ASK );
5471:
5472: if ( argc > 1 )
5473: retval = allfsck(argv+1);
5474: else {
5475: getlist();
5476: retval = allfsck(filelist);
5477: }
5478: exit(retval);
5479: }
5480:
5481:
5482: /*
5483: * perform fsck on each of the individual filesystem in list
5484: */
5485:
5486: allfsck(fsl)
5487: register char **fsl;
5488: {
5489: int fatal();
5490: int retval = 0;
5491:
5492: sync();
5493: statit("/", fatal);
5494: rootdev = stats.st_dev;
5495: while (*fsl != NULL)
5496: retval |= fsck(*fsl++);
5497: return(retval);
5498: }
5499:
5500: /*
5501: * get the names of the filesystems from the default file
5502: * checklistfile (e.g. /etc/checklist)
5503: */
5504:
5505: getlist()
5506: {
5507: int fd;
5508: int index, size;
5509:
5510: if ( (fd = open(checklistfile, 0)) == (-1) )
5511: fatal("Can't open checklist file: %s", checklistfile);
5512:
5513: index = 0;
5514: while ( ((size = getword(fd)) != 0) && (index < NFILSYS) ) {
5515: filelist[index] = malloc( size );
5516: strcpy(filelist[index++], word);
5517: }
5518:
5519: if (size != 0)
5520: fatal("Too many file systems in checklist file: %s",
5521: checklistfile);
5522:
5523: filelist[index] = NULL;
5524:
5525: close(fd);
5526: }
5527:
5528: /*
5529: * read in the next "word" from file with descriptor fd
5530: * return the length of the word.
5531: */
5532:
5533: getword(fd)
5534: int fd;
5535: {
5536: int n = 0, num;
5537: char *cp = word;
5538: char ch;
5539:
5540: while ( ( (num=read(fd, &ch, 1)) == 1 ) &&
5541: ( (ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r') ) );
5542:
5543: if (num != 1)
5544: return(0);
5545:
5546: do {
5547: *cp++ = ch;
5548: } while ( (++n < MAXCH) && (read(fd, &ch, 1) == 1) &&
5549: (ch != ' ') && (ch != '\t') && (ch != '\n') && (ch != '\r') );
5550:
5551: *cp = '\0';
5552:
5553: return(n+1);
5554: }
5555:
5556: /*
5557: * perform fsck on the given filesystem
5558: */
5559: fsck(name)
5560: char *name;
5561: {
5562: int retval = 1;
5563: int nonfatal();
5564:
5565: fsname = name; /* file system name */
5566: errflag = FALSE;
5567: statit(fsname, nonfatal);
5568: fsysrdev = stats.st_rdev;
5569: if ( errflag )
5570: return(retval);
5571: changeflg = FALSE;
5572: init();
5573: if ( sflag = ((gsflag && !mounted) || gSflag) )
5574: printf("Switch \"-s\" selected to automatically rebuild free lists\n");
5575: if (!sflag && gsflag)
5576: printf("Ignoring \"-s\" on mounted file system\n");
5577: if ( !errflag ) {
5578: phase1(); /* check blocks and sizes */
5579: if ( !fflag ) {
5580: phase2(); /* check pathnames */
5581: phase3(); /* check connectivity */
5582: phase4(); /* check reference counts */
5583: }
5584: phase5(); /* check free list */
5585: phase6(); /* salvage free list */
5586: retval = cleanup();
5587: }
5588: return(retval);
5589: }
5590:
5591: usage()
5592: {
5593: printf("\
5594: Usage: /etc/fsck [-y] [-n] [-q] [-f] [-{sS}] [-t TMPFILE] [filesystem ...]\n");
5595: _exit(1);
5596: }
5597: sflag && gsflag)
5598: printf("Ignoring \"-s\" on mounted file system\n");
5599: if ( !errflag ) {
5600: phase1(); /* check blocks and sizes */
5601: if ( !fflag ) {
5602: phase2(); /* check pathnames */
5603: phase3(); /* check connectivity fsck/objects/ 755 3 3 0 5045007474 6312 fsck/objects/main.o 644 3 3 4453 5045007122 7477 &