fsck/Makefile 644 3 3 1224 5045007365 6404 #
# for Inetco : CFLAGS = -O -DHPCOHERENT
# for PDP-11 : CFLAGS = -O
# others : CFLAGS =
#
DESTDIR=/interim/etc/
CFLAGS = -O
#
# for PDP-11 and IBM PC: LFLAGS = -i
# for Z8000 : LFLAGS =
#
LFLAGS = -i
OBJ=main.o init.o phase1.o phase1b.o phase2.o phase3.o phase4.o phase5.o\
phase6.o cleanup.o util.o printf.o link.o virtual.o is_fs.o
fsck: $(OBJ)
$(CC) $(CFLAGS) $(LFLAGS) -o $(DESTDIR)fsck $(OBJ)
#
# for IBM PC Coherent executable, use: -DNBLK=1
# for others, use : -DNBLK=8
#
# If you are running out of malloc space, try lowering the
# value of NBLK (no smaller than 1).
#
util.o: util.c
$(CC) -c $(CFLAGS) $< -DNBLK=8
$(OBJ): fsck.h
M PC: LFLAGS = -i
# for Z8000 : LFLAGS =
#
LFLAGS = -i
OBJ=main.o init.o phase1.o phase1b.o phase2.o phase3.o phase4.o phase5.o\
phase6.o cleanup.o util.o printf.o link.o virtual.o is_fs.o
fsck: $(OBJ)
$(CC) $(CFLAGS) $(LFLAGS) -o $(DESTDIR)fsck $(OBJ)
#
# for IBM PC Coherent executable, use: -DNBLK=1
# for others, use : -DNBLK=8
#
# If you are rfsck/RCS/ 755 3 3 0 5050254740 5304 fsck/RCS/Makefile,v 444 3 3 2644 5045006646 7303 head 1.3;
branch ;
access ;
symbols ;
locks bin:1.3;
comment @@;
1.3
date 91.07.29.07.44.07; author bin; state Exp;
branches ;
next 1.2;
1.2
date 91.03.15.18.33.07; author bin; state Exp;
branches ;
next 1.1;
1.1
date 91.02.08.13.26.09; author bin; state Exp;
branches ;
next ;
desc
@initial version provided byinitial version provided by epstein
@
1.3
log
@Updated by epstein for version 321.
@
text
@#
# for Inetco : CFLAGS = -O -DHPCOHERENT
# for PDP-11 : CFLAGS = -O
# others : CFLAGS =
#
CFLAGS = -O
#
# for PDP-11 and IBM PC: LFLAGS = -i
# for Z8000 : LFLAGS =
#
LFLAGS = -i
OBJ=main.o init.o phase1.o phase1b.o phase2.o phase3.o phase4.o phase5.o\
phase6.o cleanup.o util.o printf.o link.o virtual.o is_fs.o
fsck: $(OBJ)
$(CC) $(CFLAGS) $(LFLAGS) -o fsck $(OBJ)
#
# for IBM PC Coherent executable, use: -DNBLK=1
# for others, use : -DNBLK=8
#
# If you are running out of malloc space, try lowering the
# value of NBLK (no smaller than 1).
#
util.o: util.c
$(CC) -c $(CFLAGS) util.c -DNBLK=8
$(OBJ): fsck.h
@
1.2
log
@bob h added destdir, ownership, permissions...
@
text
@a6 1
DESTDIR = /interim/etc/
d16 2
a17 4
$(CC) $(CFLAGS) $(LFLAGS) -o $(DESTDIR)fsck $(OBJ)
su root chown bin $(DESTDIR)$@@
su root chgrp bin $(DESTDIR)$@@
su root chmod 511 $(DESTDIR)$@@
@
1.1
log
@Initial revision
@
text
@d7 1
d17 4
a20 2
$(CC) $(CFLAGS) $(LFLAGS) -o fsck $(OBJ)
@
unning out of malloc space, try lowering the
# value of NBLK (no smaller than 1).
#
util.o:fsck/RCS/READ_ME,v 444 3 3 1565 4754523421 6664 head 1.1;
access ;
symbols ;
locks ;
comment @@;
1.1
date 91.02.08.13.26.37; author bin; state Exp;
branches ;
next ;
desc
@updated version provided by epstein
@
1.1
log
@Initial revision
@
text
@Ideas for improving the performance of fsck:
(1) Utilize a different mechanism for storing the (struct direct)
entries throughout phase2.c, to remove implicit memory intensive
redundancy.
(2) Encode the number of links per i-node count differently, in order
to save space taking advantage of the typical usage under Coherent.
(3) Arrange space for the tables in a total needed way to avoid later
fragmentation problems affecting the memory requests for successive
file systems.
(4) Devise a more clever buffering scheme for the blocks containing
i-nodes to understand the differences between phase1, phase2, and
phase4.
@
ove implicit memory intensive
redundancy.
(2) Encode the number of links per i-node count differently, in order
to save space tfsck/RCS/cleanup.c,v 444 3 3 2652 4753557355 7452 head 1.1;
access ;
symbols ;
locks ;
comment @ * @;
1.1
date 91.02.05.16.35.30; author bin; state Exp;
branches ;
next ;
desc
@provided by Mark Epstein
@
1.1
log
@Initial revision
@
text
@/*
* Cleanup functions for phases of fsck
*/
#include "fsck.h"
cleanup()
{
int retval = 0;
if (sbpfix == TRUE)
writesuper();
prtstats();
if (changeflg == TRUE)
retval = advise();
close(fsfd);
cleanV();
return(retval);
}
writesuper()
{
register int i;
canshort(sbp->s_isize);
candaddr(sbp->s_fsize);
canshort(sbp->s_nfree);
for(i=0; i<NICFREE; i++)
candaddr(sbp->s_free[i]);
canshort(sbp->s_ninode);
for(i=0; i<NICINOD; i++)
canino(sbp->s_inode[i]);
cantime(sbp->s_time);
candaddr(sbp->s_tfree);
canino(sbp->s_tinode);
canshort(sbp->s_m);
canshort(sbp->s_n);
canlong(sbp->s_unique);
bwrite((daddr_t)SUPERI, sbp);
}
prtstats()
{
if (!fflag)
printf("%u files ", numfiles);
printf("%U blocks ", fsize - isize - totfree);
printf("%U free\n", totfree);
if ( lostsize ) {
lostsize = (lostsize + BSIZE - 1)/BSIZE;
printf("Expect roughly %U missing block%s next\n", lostsize,
(lostsize!=1) ? "s" : "" );
printf("time fsck is run as a result of inodes ");
printf("being cleared.\n");
}
}
advise()
{
int retval = 0;
printf(" ***** File System %s was modified *****\n", fsname);
if ( mounted ) {
printf(" ***** BOOT Coherent (NO SYNC!) *****\n");
retval = 1;
}
return(retval);
}
@
ocks ", fsize - isize - totfree);
printf("%U free\n", totfree);
if ( lostsize ) {
fsck/RCS/fsck.h,v 444 3 3 14557 4771205357 6775 head 1.2;
access ;
symbols ;
locks bin:1.2;
comment @ * @;
1.2
date 91.03.18.18.45.54; author bin; state Exp;
branches ;
next 1.1;
1.1
date 91.02.08.13.26.49; author bin; state Exp;
branches ;
next ;
desc
@updated version provided by epstein
@
1.2
log
@update provided by epstein
@
text
@/*
* Header file for fsck -- File System Check Program
*
*/
#include <canon.h>
#include <sys/dir.h>
#include <sys/fblk.h>
#include <sys/filsys.h>
#include <sys/ino.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#if HPCOHERENT
typedef long fsize_t;
#endif
/*
* Conditional Compilation Flags
*/
#define NOT_ALL_ZERO_INODE /* Dependent on whether or not an inode */
#ifdef ALL_ZERO_INODE /* is totally zeroed when unallocated */
#undef ALL_ZERO_INODE /* or simply a zero mode and zero link */
#endif
/*
* Definitions and Externs
*/
#define NUL 0 /* true zero ! */
#define NULL ((char *)0)
#define YES 3 /* default actions */
#define NO 2
#define ASK 1
#define NFILSYS 10 /* max number of file systems */
#define MAXCH 20 /* max length of filesys name */
#define MAXBADOK 10 /* Max number of bad blocks before excessive */
extern int numbad; /* num bad blocks found so far this inode*/
#define MAXDUPOK 10 /* Max number of dup blocks */
/* in a single inode before excessive */
#define DUPTBLSIZE 20 /* Max number of dup referenced blocks */
extern daddr_t dupblck[]; /* table of duplicate referenced blocks */
extern int totdups; /* number of dup blocks found so far */
#define MAXBADFREE 10 /* max bad in free list before abort */
#define MAXDUPFREE 10 /* max dup in free list before abort */
#define GOOD 1 /* returned by bad() in util.c */
#define BAD 0
#define TRUE 1 /* errflag possibilities */
#define FALSE 0
extern int errflag; /* errflag indicates not to do phases */
#define OK 1 /* used to indicate excessive bad/dup */
#define STOP 0 /* blocks in an inode in phase1.c */
#define BAD_DUP 2
#define FIRSTIN 2 /* First real inode number */
#define ND 10 /* Number of Direct Blocks */
#undef NI
#define NI 1
#define NII 1
#define NIII 1
#undef NADDR
#define NADDR (ND+NI+NII+NIII)
extern int offsets[]; /* table of offsets for level of indirection */
/* for the blocks in an inode */
extern char nextchar(); /* used in util.c */
extern int fsfd; /* file system file descriptor */
extern int mdaction; /* default action for this invocation */
extern int daction; /* default action for current file system */
extern int writeflg; /* system write ok or read-only */
extern int qflag; /* quiet fsck flag */
extern int fflag; /* fast fsck flag */
extern int sflag; /* force free list salvation */
extern daddr_t fsize; /* file system size in blocks */
extern int isize; /* first block not in inode list */
/* isize is NOT unsigned so that comparisons */
/* with longs will not cast the long to */
/* unsigned thus producing confusing results */
extern daddr_t totfree; /* running count of total free blocks */
extern unsigned ninodes;/* Number of inodes in the files system */
extern char *fsname; /* file system name */
extern fsize_t pinfo(); /* returns size of file, in phase2.c */
extern ino_t lostfound(); /* returns inumber of lost+found dir */
extern struct dinode *ptrino(); /* returns a ptr to inode, give number */
extern char databuf[]; /* buffer to read in block, used throughout */
extern char buf2[]; /* alternate data buffer */
extern daddr_t cdbn; /* current block number, used by nextblock() */
#define DSIZE (sizeof(struct direct))
extern char *lostname; /* name of lost+found directory */
extern char *nameit(); /* nameing function for lost dirs and files */
extern int depth; /* used during tree traversal in phase2.c */
extern struct direct *path[]; /* used during tree traversal in phase2.c */
extern char *typename(); /* return string to type of inode */
extern struct filsys *sbp; /* Super Block */
extern int sbpfix; /* flag for super block fixes */
extern struct stat stats; /* used by statit() in util.c */
extern dev_t rootdev; /* root device number */
extern dev_t fsysrdev; /* file system real device number */
extern int mounted; /* flag indicating mountedness of filesystem */
extern int changeflg; /* file system modified flag */
extern int fixerup; /* flag to rebuild free list */
extern char *fixit; /* Prompt message phase[45].c */
extern int numfiles; /* num files in system */
extern daddr_t imap(); /* function for disk block mapping in util.c */
extern fsize_t lostsize; /* Size of files cleared in phase4.c */
extern char *tmpfile; /* TMP File name for virtual.c */
#define SUCCESS 1 /* used in connect() in phase3.c */
#define FAILURE 0
#define MODEMASK 0x07
#define ALLOCMASK 0x06
#define UNALLOC 0x00
#define UNKNOWN 0x01
#define IDIR 0x02
#define IREG 0x03
#define ICHR 0x04
#define IBLK 0x05
#define IPIPE 0x06
#define IBAD_IDUP 0x08
#define VISITED 0x10
#define UNREFDIR 0x20
#define CHILDDIR 0x40
#define IFREELIST 0x80
/*
* Macros for tables
*/
#define LOGNBPC 3 /* Log2 Number of Bits per Character */
/* Actions for virtual block system */
enum vact { testBlock, markBlock, unmarkBlock, grabBlock,
testDup, markDup, unmarkDup, setDup,
Flags, setFlags, orFlags,
linkCtr, incLinkctr, setLinkctr };
#define testblock(bn) findblock((unsigned long)(bn), testBlock)
#define markblock(bn) findblock((unsigned long)(bn), markBlock)
#define unmarkblock(bn) findblock((unsigned long)(bn), unmarkBlock)
#define testdup(bn) findblock((unsigned long)(bn), testDup)
#define markdup(bn) findblock((unsigned long)(bn), markDup)
#define unmarkdup(bn) findblock((unsigned long)(bn), unmarkDup)
#define flags(ino) findblock((unsigned long)(ino), Flags)
#define setflags(ino, data) findblock((unsigned long)(ino), setFlags, data)
#define orflags(ino, data) findblock((unsigned long)(ino), orFlags, data)
#define linkctr(ino) findblock((unsigned long)(ino), linkCtr)
#define inclinkctr(ino) findblock((unsigned long)(ino), incLinkctr)
#define setlinkctr(ino, data) findblock((unsigned long)(ino), setLinkctr, data)
#define badblks(ino) ( flags(ino)&IBAD_IDUP )
/*
* Miscellany
*/
#define NBPC 8 /* number of bits per character */
#define MAXINTN 255 /* used for interleave table */
/* in phase6.c */
/*
* Stdio Stuff
*/
#define putchar(c) { char b = c; write(1, &b, 1); }
extern char *malloc();
extern char *calloc();
@
1.1
log
@Initial revision
@
text
@d85 1
@
ne inclinkctr(ino) findblock((unsigned long)(ino), incLinkctr)
#define setlinkctr(ino, data) findblock((unsigned long)(ino), setLinkctr, data)
#fsck/RCS/init.c,v 444 3 3 14501 5045006666 6767 head 1.2;
branch ;
access ;
symbols ;
locks bin:1.2;
comment @ * @;
1.2
date 91.07.29.07.44.33; author bin; state Exp;
branches ;
next 1.1;
1.1
date 91.02.05.16.36.03; author bin; state Exp;
branches ;
next ;
desc
@prov by epstein
@
1.2
log
@Updated by epstein for version 321.
@
text
@/*
* Perform initialization for phases of fsck
*/
#include "fsck.h"
#include <mnttab.h>
#include <mtab.h>
int fsfd; /* file system file descriptor */
int writeflg; /* write ok or read-only flag */
daddr_t fsize = SUPERI+1; /* file system size in blocks */
/* Allows for read of Super Block */
int isize; /* First block not in inode list */
daddr_t totfree; /* Running total free block count */
unsigned ninodes; /* number of inodes */
int numfiles; /* number of files in file system */
char superb[BSIZE]; /* Super Block */
struct filsys *sbp = superb;
int sbpfix; /* flag for super block fixes */
int offsets[] = /* table of offsets for the levels */
{ ND, ND+NI, ND+NI+NII, /* of indirection of blocks in the */
ND+NI+NII+NIII }; /* inode block list */
daddr_t dupblck[DUPTBLSIZE]; /* duplicate referenced blocks */
int totdups; /* number of dup blocks so far */
init()
{
int mode;
struct stat status;
unsigned short stmode;
mode = (mdaction == NO) ? 0 : 2;
if ( (fsfd = open(fsname, mode)) == (-1) ) {
mode = 0;
if ( (fsfd = open(fsname, mode)) == (-1) ) {
nonfatal("Can't open: %s", fsname);
return;
}
}
if (mode == 0) {
daction = NO;
writeflg = FALSE;
} else {
daction = mdaction;
writeflg = TRUE;
}
printf("%s: %s\n", fsname, (mode == 0) ? "(NO WRITE)" : "");
if ( fstat(fsfd, &status) == (-1) ) {
nonfatal("Can't stat: %s", fsname);
return;
}
stmode = status.st_mode & S_IFMT;
if ( (stmode != S_IFBLK) && (stmode != S_IFCHR) )
switch(query("file is not a block or character device; OK?")){
case YES:
break;
case NO:
errflag = TRUE;
return;
}
domount();
sbpfix = FALSE;
readsuper();
checksuper();
if ( !errflag )
alloctables();
}
/*
* Read in the super block and canonicalize
*/
readsuper()
{
register int i;
bread((daddr_t)SUPERI, superb);
sbp = superb;
canshort(sbp->s_isize);
candaddr(sbp->s_fsize);
canshort(sbp->s_nfree);
for(i=0; i<NICFREE; i++)
candaddr(sbp->s_free[i]);
canshort(sbp->s_ninode);
for(i=0; i<NICINOD; i++)
canino(sbp->s_inode[i]);
cantime(sbp->s_time);
candaddr(sbp->s_tfree);
canino(sbp->s_tinode);
canshort(sbp->s_m);
canshort(sbp->s_n);
canlong(sbp->s_unique);
}
/*
* Check super block for obvious inconsistencies
*/
checksuper()
{
fsize = sbp->s_fsize;
isize = sbp->s_isize;
totfree = fsize - isize;
if ( (isize<=INODEI) || (isize>=fsize) || (fsize<=INODEI) ) {
badsuper("Size check: fsize %U isize %u", fsize, isize);
errflag = TRUE;
}
if ( sbp->s_nfree > NICFREE )
badsuper("Too large free block count");
if ( sbp->s_ninode > NICINOD )
badsuper("Too large free i-node count");
}
/*
* Super Block Error Functions
*/
badsuper(x)
{
printf("%r\n", &x);
printf("fsck: %s: Bad Super Block: %u\n", fsname, SUPERI);
}
/*
* Allocate the necessary buffers for tables
*/
alloctables()
{
unsigned num, numl;
numl = 0;
if (!fflag) {
ninodes = (unsigned) (isize - INODEI) * INOPB;
numl = (unsigned) ninodes;
}
num = (unsigned) ((fsize+NBPC-1)/NBPC) * sizeof(char);
initV(numl, numl, num, num); /* virtual allocation */
numfiles = /* number of files in the file system */
totdups = 0; /* num dup blocks */
}
/*
* domount() checks the files /etc/mnttab and /etc/mtab to find
* out where the file system is mounted (if at all). It then
* reports where (and when if possible) it was last mounted.
*/
char *mnttab_name = "/etc/mnttab";
char *mtab_name = "/etc/mtab";
char *bttime_name = "/etc/boottime";
domount()
{
int fd;
struct mnttab mnttab;
struct mtab mtab;
register char *name;
struct stat sbuf;
time_t boottime;
int nothing();
char devname[MNTNSIZ+6] = "/dev/";
mounted = FALSE;
name = fsname; /* strip off all initial */
while (*name++ != '\0') ; /* directories in fsname */
while ( (*--name != '/') && (name>fsname) ) ;
if (*name == '/') name++;
if ( stat(bttime_name, &sbuf) == -1 )
boottime = (time_t)0;
else
boottime = sbuf.st_mtime;
if ( (fd=open(mnttab_name, 0)) != (-1) ) {
while ( read(fd, &mnttab, sizeof(mnttab))==sizeof(mnttab) )
if ( mnttab.mt_dev[0] && mnttab.mt_filsys[0] ) {
strncpy(&devname[5], mnttab.mt_filsys, MNTNSIZ);
devname[MNTNSIZ+5] = '\0';
statit(devname, nothing);
if (stats.st_rdev != fsysrdev)
continue;
statit(mnttab.mt_dev, nothing);
mounted = (stats.st_dev == fsysrdev);
prmnttab(&mnttab, boottime);
return;
}
}
if ( (fd=open(mtab_name, 0)) != (-1) ) {
while ( read(fd, &mtab, sizeof(mtab))==sizeof(mtab) )
if ( mtab.mt_name[0] && mtab.mt_special[0] ) {
strncpy(&devname[5], mtab.mt_special, MNAMSIZ);
devname[MNAMSIZ+5] = '\0';
statit(devname, nothing);
if (stats.st_rdev != fsysrdev)
continue;
statit(mtab.mt_name, nothing);
mounted = (stats.st_dev == fsysrdev);
prmtab(&mtab);
return;
}
}
if (fsysrdev == rootdev)
mounted = TRUE;
else
mounted = FALSE;
}
prmnttab(ptr, boottime)
struct mnttab *ptr;
time_t boottime;
{
if (mounted) {
if (boottime < ptr->mt_time)
boottime = ptr->mt_time;
printf("%s mounted on %.*s as of %s", fsname, MNTNSIZ,
ptr->mt_dev, ctime(&boottime));
} else
printf("%s unmounted. Last mounted on %.*s -- %s",
fsname, MNTNSIZ, ptr->mt_dev,
ctime(&ptr->mt_time));
}
prmtab(ptr)
struct mtab *ptr;
{
if (mounted)
printf("%s mounted on %.*s\n", fsname, MNAMSIZ, ptr->mt_name);
else
printf("%s unmounted. Last mounted on %.*s\n", fsname,
MNAMSIZ, ptr->mt_name);
}
nothing()
{}
@
1.1
log
@Initial revision
@
text
@d176 1
d178 1
d191 11
a201 10
if (mnttab.mt_dev[0] != '\0')
if ( strcmp(name, mnttab.mt_filsys) == 0 ) {
statit(mnttab.mt_dev, nothing);
if (stats.st_dev == fsysrdev)
mounted = TRUE;
else
mounted = FALSE;
prmnttab(&mnttab, boottime);
return;
}
d205 11
a215 10
if (mtab.mt_name[0] != '\0')
if ( strcmp(name, mtab.mt_special) == 0 ) {
statit(mtab.mt_name, nothing);
if (stats.st_dev == fsysrdev)
mounted = TRUE;
else
mounted = FALSE;
prmtab(&mtab);
return;
}
@
mt_dev[0] != '\0')
if ( strcmp(name, mnttab.mt_filsys) == 0 ) {
statit(mnttab.mt_dev, nothing);
if (stats.st_dev == fsysrdev)
mounted = TRUE;
else
mounted = FAfsck/RCS/is_fs.c,v 444 3 3 4004 4753557413 7112 head 1.1;
access ;
symbols ;
locks ;
comment @ * @;
1.1
date 91.02.05.16.36.22; author bin; state Exp;
branches ;
next ;
desc
@prov by epstein
@
1.1
log
@Initial revision
@
text
@#include <sys/stat.h>
#include <canon.h>
#include <sys/filsys.h>
/*
* Check if a special file is a well-formed filesystem.
* This routine is derived from code in "mount.c".
* Return values:
* -1 Not a device, cannot open, read or seek failed
* 0 No filesystem
* 1 Legal filesystem
*/
int
is_fs(special) char *special;
{
static struct filsys f;
struct stat sbuf;
register int fd;
register struct filsys *fp;
register daddr_t *dp;
register ino_t *ip, maxinode;
if (stat(special, &sbuf) < 0)
return -1; /* cannot stat device */
else if ((sbuf.st_mode&S_IFMT) != S_IFBLK
&& (sbuf.st_mode&S_IFMT) != S_IFCHR)
return -1; /* not a special file */
else if ((fd = open(special, 2)) < 0)
return -1; /* cannot open */
else if (lseek(fd, (long)SUPERI*BSIZE, 0) == -1L
|| read(fd, &f, sizeof(f)) != sizeof(f)) {
close(fd);
return -1; /* seek or read failed */
} else
close(fd); /* so far so good */
/* Canonical stuff. */
fp = &f;
canshort(fp->s_isize);
candaddr(fp->s_fsize);
canshort(fp->s_nfree);
for (dp = &fp->s_free[0]; dp < &fp->s_free[NICFREE]; dp += 1)
candaddr(*dp);
canshort(fp->s_ninode);
for (ip = &fp->s_inode[0]; ip < &fp->s_inode[NICINOD]; ip += 1)
canino(*ip);
candaddr(fp->s_tfree);
canino(fp->s_tinode);
/* Test for rationality. */
maxinode = (fp->s_isize - INODEI) * INOPB + 1;
if (fp->s_isize >= fp->s_fsize)
return 0;
if ((fp->s_tfree < fp->s_nfree)
|| (fp->s_tfree >= fp->s_fsize - fp->s_isize + 1))
return 0;
if ((fp->s_tinode < fp->s_ninode) || (fp->s_tinode >= maxinode-1 ))
return 0;
for (dp = &fp->s_free[0]; dp < &fp->s_free[fp->s_nfree]; dp += 1)
if ((*dp < fp->s_isize) || (*dp >= fp->s_fsize))
return 0;
for (ip = &fp->s_inode[0]; ip < &fp->s_inode[fp->s_ninode]; ip += 1)
if ((*ip < 1) || (*ip > maxinode))
return 0;
return 1;
}
@
INODEI) * INOPB + 1;
if (fp->s_isize >= fp->s_fsize)
return 0;
if ((fp->s_tfree < fp->s_nfree)
|| (fp->s_tfree >= fp->s_fsize - fp->s_isize + 1))
return 0;
if ((fp->s_tinode < fp->s_ninode) || (fp->s_tinode >= maxinode-1 ))
return 0;
for (dp = &fp->s_free[0]; dp < &fp->s_free[fp->s_nfree]; dp += 1)
if ((*dp < fp->s_isize) || (*dp >= fp->s_fsize))
return 0;
for (ip = &fp->s_inode[0]; ip < &fp->s_inode[fp->s_ninode]; ip += 1)
if ((*ip < 1) || (*ip > maxinode))
return 0;
return 1;
fsck/RCS/link.c,v 444 3 3 3277 4753557430 6756 head 1.1;
access ;
symbols ;
locks ;
comment @ * @;
1.1
date 91.02.05.16.36.34; author bin; state Exp;
branches ;
next ;
desc
@prov by epstein
@
1.1
log
@Initial revision
@
text
@/*
* Routines to handle the counting of links for each i-node
*/
#include "fsck.h"
linkincr(inum)
ino_t inum;
{
if (inclinkctr(inum) == 0 )
fatal("Too many links in i-node, %d", inum);
}
/*
* The following is the beginning of thinking of how to change
* the number of bits used in the link count tables from 8-per
* i-node to 2-per i-node, with additional tables for those
* i-nodes with more than 2 links. The changes would be to the
* definition of i_lnks, the macro linkctr(), the function linkincr(),
* and in init.c, the allocation of table space.
*/
#ifdef NEWLINKSTUFFF
char *linkmap; /* table of inodes with one link */
#define testlink(in) ( linkmap[((unsigned)bn)>>(LOGNBPC-1)] & \
3 << (((unsigned)bn)&(NBPC>>1)) )
#define marklink(in) ( linkmap[((unsigned)bn)>>(LOGNBPC-1)] |= \
1 << (((unsigned)bn)&(NBPC-2)) )
#define unmarklink(in) ( linkmap[((unsigned)bn)>>(LOGNBPC-1)] ^= \
1 << (((unsigned)bn)&(NBPC-2)) )
linkcntr(inum)
ino_t inum;
{
index = ((unsigned) inum) >> (LOGNBPC-1) ;
distance = ((unsigned) inum) & ((NBPC>>1) - 1) ;
mask = 3 << distance;
answer = ( linkmap[index] & mask ) >> distance;
if ( answer < 3 )
return(answer);
hash = inum & 0xFF;
bucket = &linktable[hash];
bktinum = bucket->inumb;
if ( bktinum == inum ) {
answer = bucket->numlink;
if ( answer == 0xFF )
return( bigcntr(inum) );
else
return( answer + 3 );
}
if ( bktinum > inum )
fatal("internal linktable corruption.");
}
linkincr(inum)
ino_t inum;
{
}
#endif
@
m) >> (LOGNBPC-1) ;
distance = ((unsigned) inum) & ((NBPC>>1) - 1) ;
mask = 3 << distance;
answer = ( linkmap[index] & mask ) >> distance;
if ( answer < 3 )
return(answer);
hash = inum & 0xFF;
bucket = &linktable[hash];
bktinum = bucket->inumb;
if ( bktinum == inum ) {
answer = bucket->numlink;
if ( ansfsck/RCS/main.c,v 444 3 3 15241 5045006700 6737 head 1.3;
branch ;
access ;
symbols ;
locks bin:1.3;
comment @ * @;
1.3
date 91.07.29.07.44.44; author bin; state Exp;
branches ;
next 1.2;
1.2
date 91.03.18.18.43.33; author bin; state Exp;
branches ;
next 1.1;
1.1
date 91.02.05.16.36.45; author bin; state Exp;
branches ;
next ;
desc
@prov by epstein
@
1.3
log
@Updated by epstein for version 321.
@
text
@/*
* fsck -- File System Check Program
* an interactive file system check and repair program.
*
* Usage:
* /etc/fsck [-y] [-n] [-q] [-f] [-{sS}] [-t TMPFILE] [filesystem ...]
* audit and interactively repair inconsistent conditions for
* file systems. Options -y and -n indicate an assumed response
* to all questions asked by fsck. Default is to prompt operator
* for yes/no response. Option -q is to quiet fsck from printing
* certain messages, i.e. no size check messages, unreferenced
* pipes will be silently removed, and counts in the superblock
* will be automatically fixed and free list salvaged, if necessary.
* Option -f is for a 'fast' check of the file system, i.e. only
* check blocks, sizes, superblock counts, and the free list.
* (-f) does not check pathnames, connectivity, or reference
* counts. Option -s forces the reconstruction (or salvaging) of
* both the free inode list and the free block list, even if there
* are no file system problems. This will reorder the free block
* list in the best order to limit additional fragmentation (respecting
* interleaving as well). Note: Option -s will be ignored on mounted
* file systems. The option -S acts in the same manner as -s except
* that it will not be ignored on mounted file systems. Beware: -S
* on mounted file systems should only be used if you intend to reboot
* NO SYNC immediately afterwards. Option -t sets the temporary file
* to use for disk caching of necessary tables on filesystems which are
* too big to do in core. The temporary file defaults to "/dev/rram1",
* which must be there.
*/
#include "fsck.h"
int errflag;
int mdaction; /* default action for invocation */
int daction; /* default action for file system */
int gSflag=FALSE; /* force salvage flag ignored mounted */
int gsflag=FALSE; /* force salvage flag ignored mounted */
int sflag=FALSE; /* force salvage flag */
int qflag=FALSE; /* fsck quiet flag */
int fflag=FALSE; /* fsck fast flag */
char *tmpfile = NULL; /* TMP file for virtual.c */
char *checklistfile = "/etc/checklist"; /* default file for list of file */
/* systems to fsck. */
char *filelist[NFILSYS]; /* list of filesystems */
char word[MAXCH]; /* hold single words */
char *fsname; /* file system name */
dev_t rootdev; /* root device number */
dev_t fsysrdev; /* file system real device number */
int mounted; /* flag for mounted file system */
int changeflg; /* file system modified flag */
main(argc, argv)
char *argv[];
{
int yflag=0, nflag=0;
int retval;
while (argc>1 && *argv[1]=='-') {
switch (argv[1][1]) {
case 'q':
qflag = TRUE;
break;
case 'y':
yflag = 1;
break;
case 'n':
nflag = 1;
break;
case 'f':
fflag = TRUE;
break;
case 'S':
gSflag = TRUE;
break;
case 's':
gsflag = TRUE;
break;
case 't':
tmpfile = argv[2];
argc--;
argv++;
break;
default:
usage();
break;
}
argc--;
argv++;
}
if ( yflag+nflag > 1 )
usage();
mdaction = ( yflag ? YES :
nflag ? NO : ASK );
if ( argc > 1 )
retval = allfsck(argv+1);
else {
getlist();
retval = allfsck(filelist);
}
exit(retval);
}
/*
* perform fsck on each of the individual filesystem in list
*/
allfsck(fsl)
register char **fsl;
{
int fatal();
int retval = 0;
sync();
statit("/", fatal);
rootdev = stats.st_dev;
while (*fsl != NULL)
retval |= fsck(*fsl++);
return(retval);
}
/*
* get the names of the filesystems from the default file
* checklistfile (e.g. /etc/checklist)
*/
getlist()
{
int fd;
int index, size;
if ( (fd = open(checklistfile, 0)) == (-1) )
fatal("Can't open checklist file: %s", checklistfile);
index = 0;
while ( ((size = getword(fd)) != 0) && (index < NFILSYS) ) {
filelist[index] = malloc( size );
strcpy(filelist[index++], word);
}
if (size != 0)
fatal("Too many file systems in checklist file: %s",
checklistfile);
filelist[index] = NULL;
close(fd);
}
/*
* read in the next "word" from file with descriptor fd
* return the length of the word.
*/
getword(fd)
int fd;
{
int n = 0, num;
char *cp = word;
char ch;
while ( ( (num=read(fd, &ch, 1)) == 1 ) &&
( (ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r') ) );
if (num != 1)
return(0);
do {
*cp++ = ch;
} while ( (++n < MAXCH) && (read(fd, &ch, 1) == 1) &&
(ch != ' ') && (ch != '\t') && (ch != '\n') && (ch != '\r') );
*cp = '\0';
return(n+1);
}
/*
* perform fsck on the given filesystem
*/
fsck(name)
char *name;
{
int retval = 1;
int nonfatal();
fsname = name; /* file system name */
errflag = FALSE;
statit(fsname, nonfatal);
fsysrdev = stats.st_rdev;
if ( errflag )
return(retval);
changeflg = FALSE;
init();
if ( sflag = ((gsflag && !mounted) || gSflag) )
printf("Switch \"-s\" selected to automatically rebuild free lists\n");
if (!sflag && gsflag)
printf("Ignoring \"-s\" on mounted file system\n");
if ( !errflag ) {
phase1(); /* check blocks and sizes */
if ( !fflag ) {
phase2(); /* check pathnames */
phase3(); /* check connectivity */
phase4(); /* check reference counts */
}
phase5(); /* check free list */
phase6(); /* salvage free list */
retval = cleanup();
}
return(retval);
}
usage()
{
printf("\
Usage: /etc/fsck [-y] [-n] [-q] [-f] [-{sS}] [-t TMPFILE] [filesystem ...]\n");
_exit(1);
}
@
1.2
log
@update provided by epstein
@
text
@d6 1
a6 1
* /etc/fsck [-y] [-n] [-q] [-f] [-s] [-t TMPFILE] [filesystem ...]
d21 7
a27 3
* interleaving as well). Option -t sets the temporary file to use
* for disk caching of necessary tables on filesystems which are too
* big to do in core. The temporary file defaults to "/dev/rram1",
d37 2
d76 3
d80 1
a80 1
sflag = TRUE;
d203 4
d224 1
a224 1
Usage: /etc/fsck [-y] [-n] [-q] [-f] [-s] [-t TMPFILE] [filesystem ...]\n");
@
1.1
log
@Initial revision
@
text
@d6 1
a6 1
* /etc/fsck [-y] [-n] [-q] [-f] [-t TMPFILE] [filesystem ...]
d17 8
a24 4
* counts. Option -t sets the temporary file to use for disk caching
* of necessary tables on filesystems which are too big to do in core.
* The temporary file defaults to "/dev/rram1", which must be there.
*
d33 3
a35 2
int qflag=FALSE; /* fsck quiet flag */
int fflag=FALSE; /* fsck fast flag */
d70 3
d211 1
a211 1
Usage: /etc/fsck [-y] [-n] [-q] [-f] [-t TMPFILE] [filesystem ...]\n");
@
g
@Initial revision
@
text
@d6 1
a6 1
* /etc/fsck [-y] [-n] [-q] [-f] [-t TMPFILE] [filesystem ...]
d17 8
a24 4
* counts. Option -t sets the temporary file to use for disk caching
* of necessary tables on filesystems which are too big to do in core.
* The temporary file defaults to "/dev/rram1", which must be there.
*
d33 3
a35 2
int qflag=FALSfsck/RCS/phase1.c,v 444 3 3 16554 4771205175 7220 head 1.2;
access ;
symbols ;
locks bin:1.2;
comment @ * @;
1.2
date 91.03.18.18.43.50; author bin; state Exp;
branches ;
next 1.1;
1.1
date 91.02.05.16.36.59; author bin; state Exp;
branches ;
next ;
desc
@prov by epstein
@
1.2
log
@update provided by epstein
@
text
@/*
* phase 1 of fsck - Check Blocks and Sizes
*/
#include "fsck.h"
char databuf[BSIZE]; /* buffer for blocks */
int clrflg; /* indicates when to clear an inode */
int dupflag; /* indicates whether there are any dups */
int numbad; /* number of bad blocks in the inode */
int numdup; /* number of duplicate blocks in inode */
long numblks; /* number of data blks for size check */
long sparsecnt; /* count for sparse blocks for size check */
/* The following is a table of the number of direct blocks pointed at by the
* four types of blocks direct, ..., triple-indirect, to help count sparse
* blocks.
*/
daddr_t blockcnt[] = {1, (daddr_t)NBN, (daddr_t)NBN*NBN, (daddr_t)NBN*NBN*NBN};
phase1()
{
if (!qflag)
printf("Phase 1 : Check Blocks and Sizes\n");
dupflag = FALSE;
inodescan();
if (dupflag)
phase1b();
}
inodescan()
{
register daddr_t bn;
register struct dinode *dip;
register ino_t ino;
int i;
ino = 1;
for (bn=INODEI; bn<isize; bn++) {
if (testblock(bn)) { /* block is bad via inode 1 */
ino += INOPB;
continue;
}
bread(bn, databuf);
clrflg = FALSE;
dip = (struct dinode *) databuf;
for (i=0; i<INOPB; i++) {
candino(dip);
if (inuse(dip) == TRUE) {
if (!fflag)
checkmode(dip, ino);
if ( checkblks(dip, ino) != STOP )
if ( qflag == FALSE )
checksize(dip, ino);
}
candino(dip);
ino++;
dip++;
}
if (clrflg)
bwrite(bn, databuf);
}
}
/*
* Determine if the given inode is in use.
*/
inuse(dip)
register struct dinode *dip;
{
#ifdef NOT_ALL_ZERO_INODE
if ( (dip->di_mode != 0) || (dip->di_nlink != 0) )
return(TRUE);
else
return(FALSE);
#endif
#ifdef ALL_ZERO_INODE
register char *ptr;
register struct dinode *next;
ptr = (char *) dip;
next = dip + 1;
while (ptr < next)
if (*ptr++ != 0)
return(TRUE);
return(FALSE);
#endif
}
/*
* Check the mode of the given inode
*/
checkmode(dip, ino)
register struct dinode *dip;
register ino_t ino;
{
register unsigned short mode;
mode = dip->di_mode & IFMT;
switch (mode) {
case IFREG:
setflags(ino, IREG);
return;
case IFDIR:
setflags(ino, IDIR);
return;
case IFCHR:
setflags(ino, ICHR);
return;
case IFBLK:
setflags(ino, IBLK);
return;
case IFPIPE:
setflags(ino, IPIPE);
return;
default:
setflags(ino, UNKNOWN);
break;
}
switch ( query("Unknown File Type i-number = %u (Clear)", ino) ){
case NO:
return;
case YES:
zeroinode(dip);
setflags(ino, UNALLOC);
clrflg = TRUE;
break;
}
}
/*
* Zero the given inode
*/
zeroinode(dip)
struct dinode *dip;
{
register char *ptr;
register struct dinode *next;
lostsize += dip->di_size;
next = dip+1;
ptr = (char *) dip;
while (ptr < next)
*ptr++ = 0;
}
/*
* Check the blocks associated with the given inode to determine
* if any are bad or duplicate
*/
checkblks(dip, ino)
struct dinode *dip;
ino_t ino;
{
daddr_t addrs[NADDR];
register daddr_t bn;
register int i, lev;
register int mode;
mode = dip->di_mode & IFMT;
if ( (mode != IFREG) && (mode != IFDIR) )
return(STOP);
l3tol(addrs, dip->di_addr, NADDR);
numbad = /* number of bad blocks so far */
numdup = /* num dup blocks so far THIS INODE */
numblks = /* num used data blocks for size chk */
sparsecnt = 0; /* count of missed data blocks */
for(i=0; i<NADDR; i++)
for (lev=0; lev<4; lev++)
if (i < offsets[lev]) {
if ( (bn=addrs[i]) != 0 ) {
if (doblocks(bn, ino, lev) != OK)
return(STOP);
} else
sparsecnt += blockcnt[lev];
break;
}
return(OK);
}
/*
* Checks recursively the blocks pointed at via
* the inode list of blocks. 'bn' is the block number,
* 'ino' is the inode referencing it, and 'lev' is the
* level 0 == direct ... 3 = triple-indirect
*/
doblocks(bn, ino, lev)
register daddr_t bn;
ino_t ino;
int lev;
{
char buf[BSIZE];
register daddr_t *bnptr;
register char *end;
register int flag;
if (lev-- == 0) { /* we have a direct block */
numblks += sparsecnt + 1;
sparsecnt = 0;
return(dodirect(bn, ino));
} else {
end = &buf[BSIZE];
if ( (flag=dodirect(bn, ino)) == OK ) {
bread(bn, buf);
bnptr = (long *) buf;
while ( bnptr < end ) {
bn = *bnptr++;
candaddr(bn);
if ( bn == 0 ) {
sparsecnt += blockcnt[lev];
continue;
}
if ( doblocks(bn, ino, lev) == STOP )
return(STOP);
}
return(OK);
} else
return(flag);
}
}
/*
* Check the given block to determine if it is bad
* or if it is a duplicate. 'ino' is the inode referencing it
*/
dodirect(bn, ino)
register daddr_t bn;
register ino_t ino;
{
register int flag;
if ( (flag=checkbad(bn, ino)) == OK )
return( checkdup(bn, ino) );
else
return(flag);
}
/*
* Check the given block number for being bad.
*/
checkbad(bn, ino)
register daddr_t bn;
ino_t ino;
{
if ( (bn>=isize) && (bn<fsize) )
return(OK);
else if ( (bn<isize) && (bn>=INODEI) && (ino == 1) ) {
/* bad block is in */
totfree++; /* the inode blocks */
return(OK);
}
if (!fflag)
orflags(ino, IBAD_IDUP);
printf("Bad block %U, i-number = %u\n", bn, ino);
if (numbad++ < MAXBADOK)
return(BAD_DUP);
switch ( query("Excessive Bad Blocks i-number = %u (Continue)", ino) ){
case NO:
abort();
case YES:
return(STOP);
}
}
/*
* Check the given block number for duplicate reference.
*/
checkdup(bn, ino)
register daddr_t bn;
ino_t ino;
{
if ( !testblock(bn) ) {
markblock(bn);
totfree--;
return(OK);
}
dupflag = TRUE;
if (!fflag)
orflags(ino, IBAD_IDUP);
printf("Dup Block %U, i-number = %u\n", bn, ino);
if (totdups < DUPTBLSIZE)
dupblck[totdups++] = bn;
else {
switch ( query("DUP Table Overflow (Continue)") ) {
case NO:
abort();
case YES:
return(BAD_DUP);
}
}
if (numdup++ < MAXDUPOK)
return(BAD_DUP);
switch ( query("Excessive Dup Blocks i-number = %u (Continue)", ino) ) {
case NO:
abort();
case YES:
return(STOP);
}
}
/*
* Check For Possible File Size Error
*/
checksize(dip, ino)
register struct dinode *dip;
ino_t ino;
{
register int mode;
register fsize_t size;
mode = dip->di_mode & IFMT;
size = dip->di_size;
if ( mode == IFREG )
filesize(ino, size);
else /* mode == IFDIR */
dirsize(dip, ino, size);
}
dirsize(dip, ino, size)
struct dinode *dip;
ino_t ino;
register fsize_t size;
{
if ( size <= 0 ) {
switch ( query("\
Bad Directory Size, size = %D, i-number = %u (Clear i-node)", size, ino) ) {
case NO:
break;
case YES:
zeroinode(dip);
setflags(ino, UNALLOC);
clrflg = TRUE;
return;
}
}
if ( size < (2*DSIZE) )
printf("Directory Size too small i-number = %u\n", ino);
if ( size % sizeof(struct direct) != 0 )
printf("Directory Misaligned i-number = %u\n", ino);
if (sizerr(size))
printf("Possible Directory Size Error i-number = %u\n", ino);
}
filesize(ino, size)
ino_t ino;
register fsize_t size;
{
if (sizerr(size))
printf("Possible File Size Error i-number = %u\n", ino);
}
sizerr(size)
register fsize_t size;
{
register fsize_t calc;
calc = (unsigned long)numblks*BSIZE;
if ( (size > calc) || ( calc >= (size+BSIZE) ) )
return(TRUE);
else
return(FALSE);
}
@
1.1
log
@Initial revision
@
text
@d152 1
d252 1
a252 1
@
saligned i-number = %u\n", ino);
if (sizerr(size))
printf("Possible Directory Size Error i-number = %u\n", ino);
}
filesize(ino, size)
ino_t infsck/RCS/phase1b.c,v 444 3 3 4676 4753557476 7362 head 1.1;
access ;
symbols ;
locks ;
comment @ * @;
1.1
date 91.02.05.16.37.12; author bin; state Exp;
branches ;
next ;
desc
@prov by epstein
@
1.1
log
@Initial revision
@
text
@/*
* Phase 1b of fsck - Rescan for more Dups
*/
#include "fsck.h"
extern int numdup; /* declared in phase1.c */
phase1b()
{
if (!qflag)
printf("Phase 1b: Rescan for more Dups\n");
buildtable();
iscanb();
}
buildtable()
{
unsigned cntr=0, numdiff=0;
daddr_t bn;
while (cntr<totdups) {
bn = dupblck[cntr++];
if (!testdup(bn)) {
markdup(bn);
numdiff++;
}
}
totdups = numdiff;
}
iscanb()
{
register daddr_t bn;
register struct dinode *dip;
register ino_t ino;
int i;
ino = 1;
for (bn=INODEI; bn<isize; bn++) {
if (testblock(bn)) { /* block is bad via inode 1 */
ino += INOPB;
continue;
}
bread(bn, databuf);
dip = (struct dinode *) databuf;
for (i=0; i<INOPB; i++) {
candino(dip);
if (inuse(dip) == TRUE)
ckblksb(dip, ino);
if (totdups == 0)
return;
ino++;
dip++;
}
}
}
/*
* Check the blocks associated with the given inode to find the
* remaining duplicate blocks
*/
ckblksb(dip, ino)
register struct dinode *dip;
register ino_t ino;
{
daddr_t addrs[NADDR];
int i, lev;
int mode;
mode = dip->di_mode & IFMT;
if ( (mode != IFREG) && (mode != IFDIR) )
return;
l3tol(addrs, dip->di_addr, NADDR);
numdup = 0; /* num dup blocks so far THIS INODE */
for(i=0; i<NADDR; i++)
for (lev=0; lev<4; lev++)
if (i < offsets[lev]) {
dblocksb(addrs[i], ino, lev);
break;
}
}
/*
* Checks recursively the blocks pointed at via
* the inode list of blocks. 'bn' is the block number,
* 'ino' is the inode referencing it, and 'lev' is the
* level 0 == direct ... 3 = triple-indirect
*/
dblocksb(bn, ino, lev)
daddr_t bn;
ino_t ino;
int lev;
{
char buf[BSIZE];
int i;
daddr_t *bnptr;
if (bn == 0)
return(OK);
switch ( cdupb(bn, ino) ) {
case OK:
if (lev--==0)
return(OK);
bread(bn, buf);
bnptr = (long *) buf;
for (i=0; i<NBN; i++) {
bn = bnptr[i];
candaddr(bn);
if ( dblocksb(bn, ino, lev) == STOP )
return(STOP);
}
return(OK);
case STOP:
return(STOP);
}
}
/*
* Check the given block number for duplicate reference.
*/
cdupb(bn, ino)
daddr_t bn;
ino_t ino;
{
if ( !testdup(bn) )
return(OK);
totdups--;
unmarkdup(bn);
if (!fflag)
orflags(ino, IBAD_IDUP);
printf("Dup Block %U, i-number = %u\n", bn, ino);
return(STOP);
}
@
)
return(OK);
bread(bn, buf);
bnptr = (long *) buf;
for (fsck/RCS/phase2.c,v 444 3 3 17750 4771205232 7212 head 1.2;
access ;
symbols ;
locks bin:1.2;
comment @ * @;
1.2
date 91.03.18.18.44.18; author bin; state Exp;
branches ;
next 1.1;
1.1
date 91.02.05.16.37.24; author bin; state Exp;
branches ;
next ;
desc
@prov by epstein
@
1.2
log
@update provided by epstein
@
text
@/*
* phase 2 of fsck - Check Pathnames
*/
#include "fsck.h"
#include <pwd.h>
#define MAXDEPTH 50
struct direct *path[MAXDEPTH];
int depth;
int fixflag; /* flags when must rewrite databuf */
daddr_t blocknum; /* Current block num read in */
typedef struct list {
struct direct d_entry;
struct list *next;
} list;
char buf2[BSIZE]; /* buffer for blocks */
daddr_t cdbn; /* current logical block number */
/* Format errors, args to blkerr() */
#define NULLNAME 5
#define NULLPAD 6
#define SLASHES 7
#define DOT 8
#define DOTDOT 9
phase2()
{
if (!qflag)
printf("Phase 2 : Check Pathnames\n");
checkroot();
depth = 0;
checkpath(ROOTIN);
}
checkroot()
{
if ( (flags(ROOTIN)&MODEMASK) == UNALLOC )
fatal("Root i-node is unallocated. Terminating");
if ( (flags(ROOTIN)&MODEMASK) != IDIR ) {
switch ( query("Root i-node is not a directory (FIX)") ){
case YES:
fixroot();
break;
case NO:
abort();
}
}
if ( badblks(ROOTIN) ){
switch ( query("Dup/Bad blocks in root i-node (Continue)") ) {
case YES:
break;
case NO:
abort();
}
}
linkincr(ROOTIN); /* (?) Feature (?) of mkfs is */
/* that root inode of a file */
/* system has a link count one */
/* too large. */
}
fixroot()
{
register struct dinode *dip;
if (!writeflg)
fatal("File System Read-Only (NO WRITE)\n");
setflags(ROOTIN, (flags(ROOTIN) & ~MODEMASK) | IDIR);
/* Save change to disk */
dip = ptrino(ROOTIN, databuf);
dip->di_mode &= (~IFMT);
dip->di_mode |= IFDIR;
writeino(ROOTIN, databuf);
}
#define myinum ( (depth>0) ? path[depth-1]->d_ino : ROOTIN )
#define popinum ( (depth>1) ? path[depth-2]->d_ino : ROOTIN )
char *memory = "Can't malloc memory, phase 2";
list *
procfiles(addrs, length)
daddr_t *addrs;
fsize_t length;
{
register struct direct *elemnt;
register list *first, *ptr;
if ((first=ptr=(list *)malloc(sizeof(list)))==NULL)
fatal(memory);
first->d_entry.d_ino = 0;
first->next = NULL;
if ( length < DSIZE )
return( first );
cdbn = 0;
nextblock(addrs);
fixflag = FALSE;
elemnt = (struct direct *) databuf;
cdots(elemnt++, ".", myinum, DOT);
++numfiles;
if ( (length-=DSIZE) < DSIZE )
return( first );
cdots(elemnt++, "..", popinum, DOTDOT);
++numfiles;
length -= DSIZE;
while ( length >= DSIZE ) {
while ( (elemnt<&databuf[BSIZE]) && (length>=DSIZE) ) {
if (chck(elemnt)==IDIR) {
copy(elemnt, &ptr->d_entry,
sizeof(struct direct));
if ((ptr->next=(list *)malloc(sizeof(list))) ==
NULL)
fatal(memory);
ptr = ptr->next;
ptr->d_entry.d_ino = 0;
ptr->next = NULL;
}
elemnt++;
length -= DSIZE;
}
if (fixflag && (fixblock(addrs) == NUL) )
fixblkerr();
nextblock(addrs);
fixflag = FALSE;
elemnt = (struct direct *) databuf;
}
return(first);
}
candblock(dptr)
register struct direct *dptr;
{
register int num, i;
num = BSIZE/sizeof(struct direct);
for (i=0; i<num; i++)
canino(dptr[i].d_ino);
}
nextblock(addrs)
register daddr_t *addrs;
{
register daddr_t bn;
if ( (bn=imap(addrs, cdbn++)) == 0 ) {
bclear(databuf, BSIZE);
return;
}
bread(bn, databuf);
candblock(databuf);
blocknum = bn;
}
fixblock(addrs)
daddr_t *addrs;
{
daddr_t bn;
if ( (bn=imap(addrs, cdbn-1)) == 0 )
return(NUL);
candblock(databuf);
bwrite(bn, databuf);
return(TRUE);
}
fixblkerr()
{
fatal("Fixblock error.");
}
copy(from, to, size)
register char *from, *to;
register int size;
{
while (size--)
*to++=*from++;
}
cdots(elemnt, dots, ino, type)
register struct direct *elemnt;
char *dots;
ino_t ino; /* what the inode number should be */
int type;
{
register char *name = elemnt->d_name;
register ino_t inum;
inum = elemnt->d_ino;
if ( (strcmp(name, dots) != 0) || (inum != ino) ||
(format(name) != GOOD) ) {
blkerr(type);
return;
}
linkincr(inum);
}
format(name)
register char *name;
{
register char *ptr=name;
register char *end=&name[DIRSIZ];
while ( (ptr<end) && (*ptr++ != '\0') ) ;
if ( (ptr-1) == name )
return(NULLNAME);
if (ptr<end) {
while ( (ptr<end) && (*ptr++ == '\0') ) ;
if (ptr!=end)
return(NULLPAD);
}
ptr = name;
while (ptr < end)
if (*ptr++ == '/')
return(SLASHES);
return(GOOD);
}
blkerr(type)
int type;
{
char *errname;
switch(type) {
case NULLNAME:
errname = "Null name";
break;
case NULLPAD:
errname = "Non null padded";
break;
case SLASHES:
errname = "Embedded slashes in";
break;
case DOT:
errname = "Inconsistent .";
break;
case DOTDOT:
errname = "Inconsistent ..";
break;
default:
errname = "Bad";
break;
}
printf("%s entry in block %U in directory\n", errname, blocknum);
pinfo(myinum);
pname(path[--depth]->d_name);
depth++;
}
chck(elemnt)
register struct direct *elemnt;
{
register ino_t inum;
register char *name;
int type;
inum = elemnt->d_ino;
if ( inum == 0 )
return(UNALLOC);
name = elemnt->d_name;
if ( (type=format(name)) != GOOD )
blkerr(type);
if (inum>ninodes) {
if ( irange(inum, name) )
zeroent(elemnt);
return(UNALLOC);
}
if ( (flags(inum)&ALLOCMASK)==UNALLOC ) {
if ( unalloc(inum, name) )
zeroent(elemnt);
return(UNALLOC);
}
if ( badblks(inum) ) {
if ( baddup(inum, name) ) {
zeroent(elemnt);
return(UNALLOC);
}
if ( (flags(inum)&MODEMASK)==IDIR )
return(UNALLOC);
}
linkincr(inum);
numfiles++;
return( flags(inum)&MODEMASK );
}
zeroent(elemnt)
struct direct *elemnt;
{
elemnt->d_ino = 0;
fixflag = TRUE;
}
pname(name)
char *name;
{
int i=0;
while (i<depth)
prdirsize(path[i++]->d_name);
prdirsize(name);
putchar('\n');
}
prdirsize(name)
char *name;
{
if (name[DIRSIZ-1] == '\0')
printf("/%s", name);
else
printf("/%*s", DIRSIZ, name);
}
fsize_t
pinfo(inum)
ino_t inum;
{
register struct dinode *dip;
register struct passwd *pwd;
if ( (dip=ptrino(inum, buf2)) == NULL ) {
printf("i-number = %u is in a bad inode block.\n", inum);
return(0);
}
printf("i-number = %u, ", inum);
if ( (pwd=getpwuid(dip->di_uid)) != NULL )
printf("Owner=%s, ", pwd->pw_name);
else
printf("Owner=%u, ", dip->di_uid);
printf(" Mode=0%o\n", dip->di_mode);
printf("Size=%U, Mtime=%s", dip->di_size, ctime(&dip->di_mtime));
return(dip->di_size);
}
char *remove = "(Remove)";
irange(inum, name)
ino_t inum;
char *name;
{
printf("I-number is out of range I=%u\n", inum);
pname(name);
return(action(remove));
}
unalloc(inum, name)
ino_t inum;
char *name;
{
fsize_t size;
printf("Unallocated\n");
size = pinfo(inum);
pname(name);
if ( (daction != NO) && (size == 0) && (mounted == FALSE) ) {
printf("%s [Forced - Yes]\n", remove);
return(YES);
}
return(action(remove));
}
baddup(inum, name)
ino_t inum;
char *name;
{
register int mode = flags(inum)&MODEMASK;
printf("Bad or Dup blocks in %s\n",(mode==IDIR) ? "Directory" : "File");
pinfo(inum);
pname(name);
return(action(remove));
}
checkpath(ino)
register ino_t ino;
{
static daddr_t addrs[NADDR];
static struct dinode *dip;
static list *temp;
register list *ptr;
if ( (flags(ino)&VISITED)==VISITED ) {
circle(ino);
return;
} else
orflags(ino, VISITED);
dip = ptrino(ino, databuf);
l3tol(addrs, dip->di_addr, NADDR);
if ( (dip->di_mode&IFMT) != IFDIR )
fatal("Tried to checkpath i-node %u which is not dir.\n", ino);
ptr = procfiles(addrs, dip->di_size);
while (ptr->d_entry.d_ino) {
if (depth >= MAXDEPTH)
toolong();
path[depth++] = &ptr->d_entry;
checkpath(ptr->d_entry.d_ino);
depth--;
temp = ptr;
ptr = ptr->next;
free(temp);
}
free(ptr);
}
circle(ino)
ino_t ino;
{
printf("I-node %u is a multiply referenced directory i-node.\n", ino);
}
toolong()
{
printf("Name too long.\n");
pname("\0");
abort();
}
@
1.1
log
@Initial revision
@
text
@d102 3
d110 3
d114 2
a115 2
numfiles += 2;
length -= 2*DSIZE; /* for the . & .. entries */
d127 1
@
r->d_entry.d_ino) {
iffsck/RCS/phase3.c,v 444 3 3 12752 5050254731 7207 head 1.2;
branch ;
access ;
symbols ;
locks bin:1.2;
comment @ * @;
1.2
date 91.08.08.09.48.33; author bin; state Exp;
branches ;
next 1.1;
1.1
date 91.02.05.16.37.54; author bin; state Exp;
branches ;
next ;
desc
@prov by epstein (post 310)
@
1.2
log
@updated by epstein to properly handle directory allocations.
@
text
@/*
* phase 3 of fsck - Check Connectivity
*/
#include "fsck.h"
char *lostname = "lost+found";
phase3()
{
ino_t i;
if (!qflag)
printf("Phase 3 : Check Connectivity\n");
for (i=FIRSTIN; i<=ninodes; i++)
if ( ((flags(i)&MODEMASK) == IDIR) &&
(linkctr(i) == 0) ) {
orflags(i, UNREFDIR);
markchildren(i);
}
for (i=FIRSTIN; i<ninodes; i++)
if ( (flags(i)&(UNREFDIR|CHILDDIR)) == UNREFDIR )
unrefdir(i);
}
markchildren(ino)
ino_t ino;
{
struct dinode *dip;
struct direct *element;
daddr_t addrs[NADDR];
ino_t inumber;
fsize_t length;
if ( badblks(ino) )
return;
dip = ptrino(ino, databuf);
if ( (length=dip->di_size) <= 0 )
return;
l3tol(addrs, dip->di_addr, NADDR);
cdbn = 0;
nextblock(addrs);
element = (struct direct *) databuf;
element += 2; /* skip over . and .. entries */
if ( (length-=2*DSIZE) <= 0 )
return;
while ( length >= DSIZE ) {
while ( (element<&databuf[BSIZE]) && (length>=DSIZE) ) {
if ( ((inumber=element->d_ino) != 0) &&
((flags(inumber)&MODEMASK)==IDIR) &&
(inumber!=ino) )
orflags(inumber, CHILDDIR);
element++;
length -= DSIZE;
}
nextblock(addrs);
element = (struct direct *) databuf;
}
}
char *reconnect = "(Reconnect)";
unrefdir(ino)
ino_t ino;
{
printf("Unref Dir\n");
if( (pinfo(ino) == 0) || (daction == NO) || (mounted == TRUE) ) {
if ( action(reconnect) == FALSE )
return;
} else
printf("%s FORCED\n", reconnect);
connect(ino, IDIR);
}
#define CONNECT 1
#define NOCONNECT 0
connect(ino, type)
ino_t ino;
int type;
{
ino_t lostino;
struct dinode *dip;
daddr_t addrs[NADDR];
fsize_t length;
struct direct *element;
int chgino = FALSE;
if ( ((lostino=lostfound()) == NUL) ||
((flags(lostino)&MODEMASK) != IDIR) ||
( badblks(lostino) ) ) {
nolost();
if (type==IDIR)
traverse(NOCONNECT, ino, lostino);
return(FAILURE);
}
dip = ptrino(lostino, buf2);
l3tol(addrs, dip->di_addr, NADDR);
length = dip->di_size;
cdbn = 0;
while ( length>=DSIZE ) {
nextblock(addrs);
element = (struct direct *) databuf;
while ( element<&databuf[BSIZE] ) {
length -= DSIZE;
if ( element->d_ino == 0 ) {
element->d_ino = ino;
strncpy(element->d_name, nameit(ino), DIRSIZ);
if ( fixblock(addrs) == NUL )
fixblkerr();
linkincr(ino);
numfiles++;
if ( length<0 ) {
dip->di_size -= length;
chgino = TRUE;
}
if ( (type == IDIR) &&
(connected(ino, lostino)==YES) ) {
dip->di_nlink++;
writeino(lostino, buf2);
traverse(CONNECT, ino, lostino);
} else if (chgino) {
writeino(lostino, buf2);
}
return(SUCCESS);
}
element++;
}
}
noroom();
if (type == IDIR)
traverse(NOCONNECT, ino, lostino);
return(FAILURE);
}
traverse(flag, ino, lostino)
int flag;
ino_t ino, lostino;
{
struct direct dirlost, nothing, newtree;
dirinit(&dirlost, lostino, lostname);
dirinit(¬hing, 0, "??");
dirinit(&newtree, ino, nameit(ino));
depth = 0;
if (flag == CONNECT)
path[depth++] = &dirlost;
else
path[depth++] = ¬hing;
path[depth++] = &newtree;
checkpath(ino);
}
dirinit(element, ino, name)
struct direct *element;
ino_t ino;
char *name;
{
element->d_ino = ino;
strncpy(element->d_name, name, DIRSIZ);
}
connected(ino, lostino)
ino_t ino; /* inumber just reconnected */
ino_t lostino; /* inumber of lostfound directory */
{
struct dinode *dip;
daddr_t addrs[NADDR];
fsize_t length;
struct direct *element;
if ( badblks(ino) ) {
badconnect(ino);
return(NO);
}
dip = ptrino(ino, databuf);
l3tol(addrs, dip->di_addr, NADDR);
length = dip->di_size;
cdbn = 0;
while ( length >= DSIZE ) {
nextblock(addrs);
element = (struct direct *) databuf;
while ( (element<&databuf[BSIZE]) && (length>=DSIZE) ) {
if ( strcmp(element->d_name, "..") == 0 ) {
printf("Dir i-number = %u connected. ", ino);
printf("Parent was i-number = %u.\n",
element->d_ino);
element->d_ino = lostino;
if ( fixblock(addrs) == NUL )
fixblkerr();
return(YES);
}
length -= DSIZE;
element++;
}
}
noparent(ino);
return(NO);
}
badconnect(ino)
ino_t ino;
{
printf("Dir i-number = %u connected. It has bad/dup blocks.\n", ino);
}
noparent(ino)
ino_t ino;
{
printf("Dir i-number = %u connected. It has no .. entry.\n", ino);
}
ino_t
lostfound()
{
static daddr_t addrs[NADDR];
struct dinode *dip;
struct direct *element;
fsize_t length;
dip = ptrino(ROOTIN, databuf);
l3tol(addrs, dip->di_addr, NADDR);
length = dip->di_size;
cdbn = 0;
while ( length>=DSIZE ) {
nextblock(addrs);
element = (struct direct *) databuf;
while ( (element<&databuf[BSIZE]) && (length>=DSIZE) ) {
if ( strcmp(element->d_name, lostname) == 0 )
return(element->d_ino);
length -= DSIZE;
element++;
}
}
return(NUL);
}
nolost()
{
printf("Sorry. No %s directory.\n", lostname);
}
noroom()
{
printf("Sorry. No space in %s directory.\n", lostname);
}
char namebuf[DIRSIZ];
char *
nameit(ino)
register ino_t ino;
{
register int i = DIRSIZ-1;
namebuf[i] = '\0';
while ( (ino != 0) && (i>0) ) {
namebuf[--i] = '0' + ino%10;
ino = ino/10;
}
return(&namebuf[i]);
}
@
1.1
log
@Initial revision
@
text
@d109 1
a130 1
length -= DSIZE;
@
eturn(element->d_ino);fsck/RCS/phase4.c,v 444 3 3 12033 4771205260 7202 head 1.2;
access ;
symbols ;
locks bin:1.2;
comment @ * @;
1.2
date 91.03.18.18.44.48; author bin; state Exp;
branches ;
next 1.1;
1.1
date 91.02.05.16.38.17; author bin; state Exp;
branches ;
next ;
desc
@prov by epstein (post 310)
@
1.2
log
@update provided by epstein
@
text
@/*
* phase 4 of fsck - Check Reference Counts
*/
#include "fsck.h"
extern char *reconnect;
fsize_t lostsize;
phase4()
{
ino_t i;
short actlink;
if (!qflag)
printf("Phase 4 : Check Reference Counts\n");
for (i=FIRSTIN; i<=ninodes; i++) {
if ( badblks(i) )
if ( bddp(i) == YES )
continue; /* inode zeroed */
if ( (linkctr(i) == 0) &&
((flags(i)&MODEMASK) != IDIR) &&
((flags(i)&ALLOCMASK) != UNALLOC) )
if ( unreflink(i) == YES )
continue; /* inode zeroed */
if ( (linkctr(i) == 0) &&
((flags(i)&ALLOCMASK) != UNALLOC) )
if ( unrefclr(i) == YES )
continue; /* inode zeroed */
if ( (actlink=getlink(i)) == (-1) ) {
i += INOPB-1;
continue; /* bad inode block */
}
if ( actlink != linkctr(i) )
linkprob(i, actlink); /* fix link count */
}
freeilist();
}
short
getlink(inum)
register ino_t inum;
{
register unsigned offset;
static ibuf[BSIZE];
register struct dinode *dip;
register daddr_t bn;
offset = iblocko(inum);
if ( (offset==0) || (inum==FIRSTIN) ) {
bn = iblockn(inum);
if ( (testblock(bn)) && (inum!=FIRSTIN) )
return(-1);
bread(bn, ibuf);
}
dip = ((struct dinode *) ibuf) + offset;
candino(dip);
return(dip->di_nlink);
}
char *clearit = "(Clear i-node)";
unreflink(ino)
ino_t ino;
{
fsize_t size;
if ( (qflag == TRUE) && ((flags(ino)&MODEMASK) == IPIPE) ) {
doclear(ino);
return(YES);
}
printf("Unref %s\n", typename(ino));
size = pinfo(ino);
if ( (daction != NO) && (size == 0) && (mounted == FALSE)
&& ((flags(ino)&MODEMASK) == IREG) ) {
printf("%s [Forced - Yes]\n", clearit);
doclear(ino);
return(YES);
}
if ( action(reconnect) == TRUE )
if( connect(ino, IREG) == FAILURE ) /* connect back in the */
return(askclear(ino)); /* non dir inode */
return(NO);
}
askclear(ino)
ino_t ino;
{
if ( action(clearit) == TRUE ) {
doclear(ino);
return(YES);
}
return(NO);
}
doclear(ino)
ino_t ino;
{
struct dinode *dip;
dip = ptrino(ino, databuf);
zeroinode(dip);
writeino(ino, databuf);
setflags(ino, UNALLOC);
setlinkctr(ino, 0);
}
char *adjust = "(Adjust)";
linkprob(ino, actlink)
ino_t ino;
short actlink;
{
printf("Link Count discrepancy in %s\n", typename(ino));
pinfo(ino);
printf("Count = %u, should be %u ", actlink, linkctr(ino));
if ( action(adjust) == TRUE )
chglink(ino);
}
chglink(ino)
ino_t ino;
{
struct dinode *dip;
dip = ptrino(ino, databuf);
dip->di_nlink = linkctr(ino);
writeino(ino, databuf);
}
unrefclr(ino)
ino_t ino;
{
printf("Unref %s\n", typename(ino));
pinfo(ino);
return(askclear(ino));
}
bddp(ino)
ino_t ino;
{
printf("Bad/Dup blocks in %s\n", typename(ino));
pinfo(ino);
return(askclear(ino));
}
char *fixit = "(FIX)";
freeilist()
{
ino_t i, count=0;
daddr_t bn;
for (i=FIRSTIN; i<=ninodes; i++)
if ( (flags(i)&ALLOCMASK) == UNALLOC )
count++;
for (bn=INODEI+1; bn<isize; bn++) /* block # INODEI can't */
if ( testblock(bn) ) /* be bad since ROOTIN */
count -= INOPB; /* is in it, otherwise */
/* big time bad news. */
if ( sbp->s_tinode != count )
if ( (qflag==FALSE) && (daction!=NO) ) {
printf("Free i-node count wrong in superblock. ");
if ( action(fixit) == TRUE ) {
sbp->s_tinode = count;
sbpfix = TRUE;
}
} else {
sbp->s_tinode = count;
sbpfix = TRUE;
}
if ( (daction!=NO) &&
( (sflag==TRUE) || (sbpfix==TRUE) || (badilist()==BAD) ) )
rebuild();
}
badilist()
{
ino_t i, inum;
unsigned numfree;
daddr_t bn;
if ( (numfree=(unsigned) sbp->s_ninode) > NICINOD )
return(BAD);
for (i=0; i<numfree; i++) {
inum = sbp->s_inode[i];
bn = iblockn(inum);
if ( (testblock(bn)) && (bn!=INODEI) )
return(BAD);
if ( (inum < FIRSTIN) || (inum > ninodes) )
return(BAD);
if ( (flags(inum)&ALLOCMASK) != UNALLOC )
return(BAD);
if ( flags(inum)&IFREELIST )
return(BAD); /* dup in ifree list */
orflags(inum, IFREELIST);
}
return(GOOD);
}
rebuild()
{
daddr_t bn;
ino_t i;
int index;
sbpfix = TRUE;
for (i=FIRSTIN, index=0; (i<=ninodes) && (index<NICINOD); i++) {
if ( (flags(i)&ALLOCMASK) == UNALLOC ) {
bn = iblockn(i);
if ( (!testblock(bn)) || (bn==INODEI) )
index++;
}
}
sbp->s_ninode = index;
for (i=FIRSTIN; (i<=ninodes) && (index>0); i++) {
if ( (flags(i)&ALLOCMASK) == UNALLOC ) {
bn = iblockn(i);
if ( (!testblock(bn)) || (bn==INODEI) )
sbp->s_inode[--index] = i;
}
}
printf("Free i-node list in superblock rebuilt.\n");
}
@
1.1
log
@Initial revision
@
text
@a16 1
lostsize = 0;
a108 1
lostsize += dip->di_size;
d181 2
a182 1
if ( (daction!=NO) && ((sbpfix==TRUE) || (badilist()==BAD)) )
d214 2
a215 2
ino_t i = FIRSTIN;
int index = 0;
d218 1
a218 1
while ( (i<=ninodes) && (index<NICINOD) ) {
d222 1
a222 1
sbp->s_inode[index++] = i;
a223 1
i++;
a224 1
d226 7
@
bn = iblockn(i);
if ( (!testblock(bn)) || (bn==INODEI) )
sbp->s_inode[--index] = i;
}
}
printf("Free i-node list in superblock rebuilt.\n");
}
@
1.1
log
@Initial revision
@
text
@a16 1
lostsize = 0;
a108 1
lostsize += dip->di_size;
d181 2
a182 1
if ( (daction!=NO) && ((sbpfix==TRUE) || (badilist()==BAD)) )
d214 2
a215 2
ino_t i = FIRSTIN;
int index = 0;
d218 1
a218 1
while ( (i<=ninodes) && (index<NICINOD) ) {
d222 1
a222 1
sbp->s_inode[index++] = i;
a223fsck/RCS/phase5.c,v 444 3 3 7463 4771205275 7204 head 1.2;
access ;
symbols ;
locks bin:1.2;
comment @ * @;
1.2
date 91.03.18.18.45.05; author bin; state Exp;
branches ;
next 1.1;
1.1
date 91.02.05.16.38.33; author bin; state Exp;
branches ;
next ;
desc
@prov by epstein (phase5.c)
@
1.2
log
@update provided by epstein
@
text
@/*
* phase 5 of fsck - Check Free List
*/
#include "fsck.h"
daddr_t badcnt; /* Number of bad blocks in free list */
daddr_t dupcnt; /* Number of dup blocks in free list */
int badflag; /* Bad free list flag */
int fixerup; /* Flag to salvage free list */
phase5()
{
struct fblk *fbp;
unsigned size;
if (!qflag)
printf("Phase 5 : Check Free List\n");
fbp = (struct fblk *) &sbp->s_nfree;
size = (unsigned) ((fsize+NBPC-1)/NBPC) * sizeof(char);
copyV(size);
badcnt = dupcnt = 0;
badflag = FALSE;
freetrav(fbp);
fixerup = FALSE;
if (badflag || sflag)
asksalvage();
}
#define IGNORE 3 /* Return Possibilities from chk() */
#define ABORT 4 /* as well as perhaps GOOD and BAD */
freetrav(fbp)
struct fblk *fbp;
{
daddr_t total=0;
int i, flag;
while ( fbp->df_nfree != 0 ) {
if ( (unsigned) fbp->df_nfree > NICFREE ) {
badflag = TRUE;
printf("Bad freeblock count.\n");
break;
}
for (i=1; i<fbp->df_nfree; i++) {
if ( (flag=chk(fbp->df_free[i])) == GOOD ) {
total++;
continue;
}
if (flag == BAD)
continue;
break; /* break for IGNORE or ABORT */
}
if ( (flag == IGNORE) || (flag == ABORT) )
break;
if ( chk(fbp->df_free[0]) != GOOD )
break;
total++;
bread(fbp->df_free[0], databuf);
fbp = (struct fblk *) databuf;
if ( !canfblk(fbp) ) {
badflag = TRUE;
printf("Bad freeblock count.\n");
break;
}
}
#if 0
printf("Total traversed free blocks = %U\n", total);
printf("Total free blocks by Superblock = %U\n", sbp->s_tfree);
printf("Running total free blocks = %U\n", totfree);
#endif
if ( flag == ABORT ) { /* To Terminate fsck on this */
badflag = FALSE; /* File System, because of */
return; /* excessive dup or bad blocks */
}
if ( sbp->s_tfree != totfree )
if ( (qflag==FALSE) && (daction!=NO) ) {
printf("Free Block count wrong in superblock. ");
if ( action(fixit) == TRUE ) {
sbp->s_tfree = totfree;
sbpfix = TRUE;
}
} else {
sbp->s_tfree = totfree;
sbpfix = TRUE;
}
report("%U Bad Block%s in Free List\n", badcnt);
report("%U Dup Block%s in Free List\n", dupcnt);
report("%U Block%s missing\n", totfree - total);
}
report(message, num)
char *message;
daddr_t num;
{
if ( num != 0 ) {
printf(message, num, ( (num>1) ? "s" : "" ) );
badflag = TRUE;
}
}
chk(bn)
register daddr_t bn;
{
if ( (bn<isize) || (bn>=fsize) ) {
badflag = TRUE;
if (++badcnt > MAXBADFREE)
return( stopit("bad") );
return(BAD);
}
if ( testdup(bn) ) {
badflag = TRUE;
if (++dupcnt > MAXDUPFREE)
return( stopit("dup") );
return(BAD);
} else {
markdup(bn);
return(GOOD);
}
}
stopit(type)
char *type;
{
printf("Excessive %s blocks in free list ", type);
if ( query("(Continue)") == YES )
return(IGNORE);
else
return(ABORT);
}
canfblk(fbp)
register struct fblk *fbp;
{
register short i;
canshort(fbp->df_nfree);
if ( (unsigned) fbp->df_nfree > NICFREE )
return(FALSE);
for (i=0; i<fbp->df_nfree; i++)
candaddr(fbp->df_free[i]);
return(TRUE);
}
asksalvage()
{
if ( (daction!=NO) && (qflag || sflag) ) {
fixerup = TRUE;
return;
}
if ( action("Bad Free List (SALVAGE)") )
fixerup = TRUE;
}
@
1.1
log
@Initial revision
@
text
@d26 1
a26 1
if (badflag)
d62 5
a66 1
canfblk(fbp);
d69 5
a73 3
/* printf("Total traversed free blocks = %U\n", total); */
/* printf("Total free blocks by Superblock = %U\n", sbp->s_tfree); */
/* printf("Running total free blocks = %U\n", totfree); */
d146 3
d151 2
a153 2
}
d156 1
a156 1
if ( qflag && (daction!=NO) ) {
@
( (daction!=NO) && (qflag || sflag) ) {
fixerup = TRUE;
return;
}
if ( action("Bad Free List (SALVAGE)") )
fixerup = TRUE;
}
@
1.1
log
@Initial revision
@
text
@d26 1
a26 1
if (badflag)
d62 5
afsck/RCS/phase6.c,v 444 3 3 5736 4771205312 7176 head 1.2;
access ;
symbols ;
locks bin:1.2;
comment @ * @;
1.2
date 91.03.18.18.45.18; author bin; state Exp;
branches ;
next 1.1;
1.1
date 91.02.05.16.38.52; author bin; state Exp;
branches ;
next ;
desc
@prov by epstein (post 310)
@
1.2
log
@update provided by epstein.
@
text
@/*
* phase 6 of fsck - Salvage Free List
*/
#include "fsck.h"
static unsigned char *maptab; /* table of interleave offsets */
static daddr_t mapbot; /* minimum block number to interleave map */
static daddr_t maptop; /* maximum block number to interleave map */
static short m,n; /* interleave factors */
#define DEF_N 1 /* default values */
#define DEF_M 1
daddr_t freeblks; /* number free blocks left to write out */
daddr_t blknm; /* current block number we are working with */
struct fblk *fblkp; /* pointer to free block list */
daddr_t *dp; /* pointer to block entry in free list block */
phase6()
{
if (!fixerup) {
return;
}
if (!qflag)
printf("Phase 6 : Salvage Free List\n");
if ( maketable() == BAD )
return;
writefree();
free(maptab);
}
maketable()
{
register int i;
register int ratio;
m = sbp->s_m;
n = sbp->s_n;
if ( (n > MAXINTN) || (m > n) || (n%m != 0) ) {
printf("Invalid interleave factors in superblock.\n");
printf("Default free-block list spacing assumed.\n");
sbp->s_n = n = DEF_N;
sbp->s_m = m = DEF_M;
}
if ( (maptab = malloc(n)) == NULL ) {
printf("Can't malloc space for interleave table.\n");
printf("Free-block list is not rebuilt.\n");
return(BAD);
}
mapbot = (isize + n - 1)/n*n;
maptop = fsize/n*n;
ratio = n/m;
for (i=0; i<n; i++)
maptab[i] = (i/ratio) + (i%ratio)*m;
return(GOOD);
}
writefree()
{
register daddr_t bn;
daddr_t blk, bmap();
short num;
sbpfix = TRUE;
freeblks = totfree;
blknm = SUPERI;
fblkp = (struct fblk *) &sbp->s_nfree;
fblkp->df_nfree = num = (freeblks < NICFREE) ? freeblks : NICFREE;
freeblks -= num;
dp = &fblkp->df_free[num];
for (bn=isize; bn<fsize; bn++) {
blk = bmap(bn);
if ( !testblock(blk) )
if ( addfree(blk) == STOP )
break;
}
}
addfree(bn)
daddr_t bn;
{
short num;
*--dp = bn;
if (dp > &fblkp->df_free[0])
return(OK);
if ( blknm != SUPERI ) {
canwfblk(fblkp);
bwrite(blknm, databuf);
}
bclear(databuf, BSIZE);
if (freeblks == 0) {
bwrite(bn, databuf);
return(STOP);
}
blknm = bn;
fblkp = (struct fblk *) databuf;
fblkp->df_nfree = num = (freeblks < NICFREE) ? freeblks : NICFREE;
freeblks -= num;
dp = &fblkp->df_free[num];
return(OK);
}
daddr_t
bmap(blk)
register daddr_t blk;
{
short i;
if ( (blk>=mapbot) && (blk<maptop) ) {
i = blk%n;
blk -= i;
blk += maptab[i];
}
return(blk);
}
canwfblk(fbp)
register struct fblk *fbp;
{
register short i;
for (i=0; i<fbp->df_nfree; i++)
candaddr(fbp->df_free[i]);
canshort(fbp->df_nfree);
}
@
1.1
log
@Initial revision
@
text
@d7 1
a7 1
static char *maptab; /* table of interleave offsets */
d114 1
a114 1
int i;
d117 3
a119 2
i = ((unsigned)blk)%n;
blk += maptab[i] - i;
@
rn(OK);
}
daddr_t
bmap(blk)
regisfsck/RCS/printf.c,v 444 3 3 7620 4753557667 7333 head 1.1;
access ;
symbols ;
locks ;
comment @ * @;
1.1
date 91.02.05.16.39.10; author bin; state Exp;
branches ;
next ;
desc
@prov by epstein (post310)
@
1.1
log
@Initial revision
@
text
@/*
* Standard output printf using putchar.
* Non-portable things:
* 1) alignment of arguments is assumed to be completely contiguous.
* 2) the smallest number is assumed to negate to itself.
* 3) All of long, int, char*, and double are assumed to
* be held in an exact number of ints.
*/
#define NULL ((char *)0)
#define putchar(c) { char b = c; write(1, &b, 1); }
#include <sys/mdata.h>
union alltypes {
char c;
int i;
unsigned u;
long l;
double d;
char *s;
};
#define bump(p,s) (p+=sizeof(s)/sizeof(int))
char *printi();
char *printl();
static char null[] = "{NULL}";
printf(args)
union alltypes args;
{
xprintf(&args);
}
xprintf(argp)
union alltypes *argp;
{
register char *cbp;
int *iap;
register c;
char *s;
char *cbs;
char adj, pad;
int prec;
int fwidth;
int pwidth;
register char *fmt;
union alltypes elem;
char cbuf[64];
iap = (int *)argp;
fmt = *(char **)iap;
bump(iap, char*);
for (;;) {
while((c = *fmt++) != '%') {
if(c == '\0') {
return;
}
putchar(c);
}
pad = ' ';
fwidth = -1;
prec = -1;
c = *fmt++;
if (c == '-') {
adj = 1;
c = *fmt++;
} else
adj = 0;
if (c == '0') {
pad = '0';
c = *fmt++;
}
if (c == '*') {
fwidth = *iap++;
c = *fmt++;
} else
for (fwidth = 0; c>='0' && c<='9'; c = *fmt++)
fwidth = fwidth*10 + c-'0';
if (c == '.') {
c = *fmt++;
if (c == '*') {
prec = *iap++;
c = *fmt++;
} else
for (prec=0; c>='0' && c<='9'; c=*fmt++)
prec = prec*10 + c-'0';
}
if (c == 'l') {
c = *fmt++;
if (c=='d' || c=='o' || c=='u' || c=='x')
c += 'A' - 'a';
}
cbp = cbs = cbuf;
switch (c) {
case 'd':
elem.i = *iap++;
if (elem.i < 0) {
elem.i = -elem.i;
*cbp++ = '-';
}
cbp = printi(cbp, elem.i, 10);
break;
case 'u':
cbp = printi(cbp, *iap++, 10);
break;
case 'o':
cbp = printi(cbp, *iap++, 8);
break;
case 'x':
cbp = printi(cbp, *iap++, 16);
break;
case 'D':
elem.l = *(long *)iap;
bump(iap, long);
if (elem.l < 0) {
elem.l = -elem.l;
*cbp++ = '-';
}
cbp = printl(cbp, elem.l, 10);
break;
case 'U':
cbp = printl(cbp, *(long *)iap, 10);
bump(iap, long);
break;
case 'O':
cbp = printl(cbp, *(long *)iap, 8);
bump(iap, long);
break;
case 'X':
cbp = printl(cbp, *(long *)iap, 16);
bump(iap, long);
break;
case 's':
if ((s = *(char **)iap) == NULL)
s = null;
bump(iap, char*);
/*
* Do %s specially so it can be longer.
*/
cbp = cbs = s;
while (*cbp++ != '\0')
if (prec>=0 && cbp-s>prec)
break;
cbp--;
break;
case 'c':
elem.c = *iap++;
*cbp++ = elem.c;
break;
case 'r':
xprintf(*(char ***)iap);
bump(iap, char**);
break;
default:
putchar(c);
continue;
}
if ((pwidth = fwidth + cbs-cbp) < 0)
pwidth = 0;
if (!adj)
while (pwidth-- != 0)
putchar(pad);
while (cbs < cbp)
putchar(*cbs++);
if (adj)
while (pwidth-- != 0)
putchar(pad);
}
}
static char digits[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'
};
/*
* Print an unsigned integer in base b.
*/
static
char *
printi(cp, n, b)
char *cp;
register unsigned n;
{
register a;
register char *ep;
char pbuf[10];
ep = &pbuf[10];
*--ep = 0;
for ( ; a = n/b; n=a)
*--ep = digits[n%b];
*--ep = digits[n];
while (*ep)
*cp++ = *ep++;
return (cp);
}
/*
* Print an unsigned long in base b.
*/
static
char *
printl(cp, n, b)
register char *cp;
unsigned long n;
register b;
{
char pbuf[13];
unsigned long a;
register char *ep;
ep = &pbuf[13];
*--ep = '\0';
for ( ; (a = n/b) != 0; n = a)
*--ep = digits[n%b];
*--ep = digits[n];
while (*ep)
*cp++ = *ep++;
return (cp);
}
@
egister char *ep;
char pbuf[10];
ep = &pbuf[10];
*--ep = 0;
for ( ; a = n/b; n=a)
*--ep = digits[n%b];
*fsck/RCS/util.c,v 444 3 3 16442 5045006750 7001 head 1.2;
branch ;
access ;
symbols ;
locks bin:1.2;
comment @ * @;
1.2
date 91.07.29.07.45.21; author bin; state Exp;
branches ;
next 1.1;
1.1
date 91.02.05.16.39.25; author bin; state Exp;
branches ;
next ;
desc
@prov by epstein (post 310)
@
1.2
log
@Updated by epstein for version 321.
@
text
@/*
* general utility functions for phases of fsck
*/
#include "fsck.h"
struct stat stats; /* Used by statit() */
statit(name, probfun)
char *name;
int (*probfun)();
{
if ( stat(name, &stats) == -1 ) {
bclear(&stats, sizeof(struct stat));
(*probfun)("Can not stat %s", name);
}
}
query(x)
{
while(1) {
printf("%r [yes/no]: ", &x);
switch (daction) {
case YES:
printf("[default - YES]\n");
return(YES);
break;
case NO:
printf("[default - NO]\n");
return(NO);
break;
case ASK:
switch( nextchar() ) {
case 'Y':
return(YES);
case 'N':
return(NO);
}
}
}
}
action(msg)
char *msg;
{
switch( query(msg) ) {
case YES:
return(TRUE);
case NO:
return(FALSE);
}
}
char
nextchar()
{
char buff[8];
int i, n, ch;
if ( ((n=read(0,buff,8)) <= 0) || (n == 8) )
fatal("Invalid Response");
for(i=0; i<n; i++)
if ( ((ch=buff[i])!=' ') && (ch!='\t') )
break;
if ( (ch>='a') && (ch<='z') )
ch += 'A' - 'a';
return(ch);
}
char *nfile = "FILE";
char *ndir = "DIR";
char *nchr = "Character Special";
char *nblk = "Block Special";
char *npipe = "PIPE";
char *nunkwn = "Unknown I-node type";
char *
typename(ino)
ino_t ino;
{
switch( flags(ino)&MODEMASK ) {
case IREG:
return(nfile);
case IDIR:
return(ndir);
case ICHR:
return(nchr);
case IBLK:
return(nblk);
case IPIPE:
return(npipe);
default:
return(nunkwn);
}
}
abort()
{
fatal("abort.");
}
fatal(x)
{
printf("fsck: %r\n", &x);
_exit(1);
}
nonfatal(x)
{
printf("fsck: %r\n", &x);
errflag = TRUE;
}
/*
* Inode Manipulation Routines
* ptrino: returns a pointer to the wanted inode using the given
* buffer to read in the block performing canonicalization.
* writeino: writes the block containing the given inode to the
* disk performing the necessary canonicalization
* candino: canonicalize an inode
*
*/
struct dinode *
ptrino(ino, buf)
register ino_t ino;
register char *buf;
{
register daddr_t bn;
register struct dinode *dip;
bn = iblockn(ino);
if ( (testblock(bn)) && (bn!=INODEI) ) /* bad inode block */
return(NULL);
bread(bn, buf);
dip = ((struct dinode *) buf) + iblocko(ino);
candino(dip);
return(dip);
}
writeino(ino, buf)
ino_t ino;
char *buf;
{
struct dinode *dip;
dip = ((struct dinode *) buf) + iblocko(ino);
candino(dip);
bwrite((daddr_t) iblockn(ino), buf);
}
candino(dip)
register struct dinode *dip;
{
canshort(dip->di_mode);
canshort(dip->di_nlink);
canshort(dip->di_uid);
canshort(dip->di_gid);
cansize(dip->di_size);
cantime(dip->di_atime);
cantime(dip->di_mtime);
cantime(dip->di_ctime);
}
/*
* Transfer a logical block number for an inode to a
* physical block number, chasing indirects as necessary.
* The inefficiency of this method is put up with since
* this is only used for directory inodes, and they tend
* not to use indirects. Pass in 'addrs' which is a pointer
* to the 13 daddr_s in the inode, and the logical block
* number you would like. (Stolen from dcheck.c)
*/
static daddr_t ranges[] = {
ND,
ND + (daddr_t)NI*NBN,
ND + (daddr_t)NI*NBN + (daddr_t)NII*NBN*NBN,
ND + (daddr_t)NI*NBN + (daddr_t)NII*NBN*NBN + (daddr_t)NIII*NBN*NBN*NBN
};
static char index[] = {
0,
ND,
ND+NI,
ND+NI+NII
};
static daddr_t coeff[] = {
1, (daddr_t)NBN, (daddr_t)NBN*NBN, (daddr_t)NBN*NBN*NBN
};
daddr_t
imap(addrs, block)
daddr_t *addrs;
register daddr_t block;
{
int i;
register daddr_t bpos;
register daddr_t *bp;
register daddr_t bn;
for (i=0; i<4; i++)
if (block < ranges[i]) {
if (i != 0)
block -= ranges[i-1];
bpos = block/coeff[i];
block %= coeff[i];
bp = &addrs[(int)bpos + index[i]];
if ( (bn=*bp) != 0 ) {
/*
* Map through indirects here
*/
while (i-- > 0) {
bread(bn, databuf);
bpos = block/coeff[i];
block %= coeff[i];
bp = (daddr_t *)databuf + bpos;
if ( (bn=*bp) == 0 )
break;
bn = *bp;
candaddr(bn);
}
}
return(bn);
}
return(0);
}
/*
* Read the specified block number into the given buffer
*/
char *rgblkerr = "Out of Range Block number: %U (CONTINUE)";
char *skblkerr = "Can not Seek: Blk num: %U (CONTINUE)";
char *rdblkerr = "Can not Read: Blk num: %U (CONTINUE)";
char *wtblkerr = "Can not Write: Blk num: %U (CONTINUE)";
bread(bn, buf)
register daddr_t bn;
register char *buf;
{
#ifdef DEBUG
printf("Reading block number: %ld\n", bn);
#endif
if (bn<0 || bn >= fsize )
switch( query(rgblkerr, bn) ) {
case YES:
bclear(buf, BSIZE);
return;
case NO:
abort();
}
if ( (bn<isize) && getcache(bn, buf) ) {
#if DEBUG
bdump(buf);
#endif
return;
}
if ( lseek(fsfd, (unsigned long)bn*BSIZE, 0) == (-1L) )
switch( query(skblkerr, bn) ) {
case YES:
bclear(buf, BSIZE);
return;
case NO:
abort();
}
if ( read(fsfd, buf, BSIZE) != BSIZE )
switch( query(rdblkerr, bn) ) {
case YES:
bclear(buf, BSIZE);
return;
case NO:
abort();
}
#if DEBUG
bdump(buf);
#endif
}
/*
* Write block number bn with data in buf
*/
bwrite(bn, buf)
daddr_t bn;
char *buf;
{
#ifdef DEBUG
printf("Writing block number: %ld\n", bn);
#endif
if (!writeflg)
return;
if (bn<0 || bn>=fsize)
switch( query(rgblkerr, bn) ) {
case YES:
return;
case NO:
abort();
}
if ( lseek(fsfd, (fsize_t)BSIZE*bn, 0) == (-1L) )
switch( query(skblkerr, bn) ) {
case YES:
return;
case NO:
abort();
}
if ( write(fsfd, buf, BSIZE) != BSIZE )
switch( query(wtblkerr, bn) ) {
case YES:
return;
case NO:
abort();
}
if ( bn <= isize )
chgcache(bn, buf);
changeflg = TRUE;
}
/*
* i-node block area caching routines
*/
static char cache[NBLK * BSIZE];
static int low = 0; high = -1;
getcache(bn, buf)
register daddr_t bn;
register char *buf;
{
int totsize;
if ( bn > isize )
return(0);
if ( (bn>=low) && (bn<=high) ) {
blkmove(buf, &cache[BSIZE * (bn-low)]);
return(1);
}
low = bn;
if ( (high=bn+NBLK-1) > isize )
high = isize;
totsize = BSIZE * (high-low+1);
if ( (lseek(fsfd, (unsigned long)bn*BSIZE, 0) == (-1L)) ||
(read(fsfd, cache, totsize) != totsize) ) {
low = 0; high = -1;
return(0);
}
return( getcache(bn, buf) );
}
chgcache(bn, buf)
register daddr_t bn;
register char *buf;
{
if ( (bn>=low) && (bn<=high) )
blkmove(&cache[BSIZE * (bn-low)], buf);
}
blkmove(to, from)
register char *to, *from;
{
register int num=BSIZE;
while ( num-- )
*to++= *from++;
}
/*
* Clear the given block of memory
*/
bclear(bp, nb)
register char *bp;
register unsigned nb;
{
if (nb)
do {
*bp++ = 0;
} while (--nb);
}
/*
* Determine if the given block is bad
*/
bad(bn)
daddr_t bn;
{
if ( (bn >= isize) && (bn < fsize) )
return(GOOD);
else
return(BAD);
}
#if DEBUG
/*
* Debug dump a block of data.
*/
#define NUMPLIN 16
bdump(buf)
register unsigned char *buf;
{
register int i;
for (i=0; i<BSIZE; i++) {
if ( (i % NUMPLIN) == 0 )
printf("\n0x%04x: ", i);
printf(" %02x", *buf++);
}
printf("\n\n");
}
#endif
@
1.1
log
@Initial revision
@
text
@d261 4
a264 1
if ( (bn<isize) && getcache(bn, buf) )
d266 1
d285 3
d412 24
@
iven block is bad
*/
bad(bn)
daddr_t bn;
{
if ( (bn >= isize) && (bn < fsize) )
return(GOOD);
else
return(BAD);
}
#if DEBUG
/*
* Debug dump a block of data.
*/
#define NUMPLIN 16
bdump(buf)
register unsignefsck/RCS/virtual.c,v 444 3 3 16557 4753557734 7543 head 1.1;
access ;
symbols ;
locks ;
comment @ * @;
1.1
date 91.02.05.16.39.42; author bin; state Exp;
branches ;
next ;
desc
@prov by epstein (post 310)
@
1.1
log
@Initial revision
@
text
@/*
* Virtual memory for fsck. Uses hash algorithm
* rather than LRU to get it up fast.
*/
#include <assert.h>
#include <sys/stat.h>
#include "fsck.h"
#define VBLKB 9 /* bytes in virtual block as power of 2 */
#define VBLK (1 << VBLKB) /* bytes in a virtual block */
#define MBKSB 6 /* number of virtual blocks as power of 2 */
#define MBKS (1 << MBKSB) /* number of virtual blocks */
#define DVTMP "/dev/rram1" /* Default Virtual Temp Filename */
#define DVTMPCLS "/dev/rram1close" /* Default Virtual Temp File Close */
#define MAJORRAM 8 /* Major Device Number for the Ram Disk */
struct mapper {
unsigned dirty:1;
unsigned what_in:15; /* which block is in memory */
};
static unsigned long flagdsp, blkdsp, dupdsp, duplim;
static struct mapper map[MBKS];
static unsigned char data[MBKS][VBLK];
static int tmp;
static char *dvtmp = DVTMP;
static char *dvtmpcls = DVTMPCLS;
/*
* Init file system for virtual arrays.
* Data is ordered links, flags, blocks then dups.
*/
initV(links, flags, blocks, dups)
unsigned links, flags, blocks, dups;
{
register long bp;
struct stat st;
unsigned datasiz;
flagdsp = links;
blkdsp = flagdsp + flags;
dupdsp = blkdsp + blocks;
duplim = dupdsp + dups;
memset(map, 0, sizeof(map)); /* zero ram arrays */
memset(data, 0, sizeof(data));
tmp = -1;
datasiz = sizeof(data);
if ( duplim < datasiz )
return;
if ( tmpfile == NULL ) {
switch ( is_fs(dvtmp) ) {
case -1:
fatal(
"Can't access ram disk \"%s\", use the -t option", dvtmp);
case 0:
break;
case 1:
fatal(
"Possible file system on ram disk \"%s\", use the -t option", dvtmp);
}
if ( (-1 == stat(dvtmp, &st)) || !(st.st_mode&S_IFCHR) ||
(major(st.st_rdev) != MAJORRAM) )
fatal("Ram disk \"%s\" not mknod'ed properly",
dvtmp);
if ( -1 == (tmp = open(dvtmp, 2)) )
fatal("Cannot open read/write Ram Disk \"%s\"", dvtmp);
/* Ram disk driver may not promise zeroed start.
* This code may go later. Extra write not important. */
for(bp = 0; bp < duplim; bp += VBLK) /* zero disk stuff */
if ( VBLK != write(tmp, data[0], VBLK) )
fatal("Error writing to tmp file");
} else {
if ( -1 == (tmp = open(tmpfile, 2)) ) {
if ( -1 == (tmp = creat(tmpfile, 0600)) )
fatal("Cannot create temp file \"%s\"",
tmpfile);
close(tmp);
tmp = open(tmpfile, 2);
unlink(tmpfile);
}
if ( -1 == fstat(tmp, &st) )
fatal("Can't stat temp file \"%s\"", tmpfile);
if ( st.st_dev == fsysrdev )
fatal("Temp File must not be on file system to fsck");
}
}
/*
* cleanup virtual system
*/
cleanV()
{
struct stat st;
if ( tmp == -1 ) /* No Virtual Temp File Opened */
return;
close(tmp);
if ( tmpfile != NULL ) /* Virtual File not Default RAMDisk */
return;
/* Virtual File is Default RAMDisk */
if ( (-1 == stat(dvtmpcls, &st)) || !(st.st_mode&S_IFCHR) ||
(major(st.st_rdev) != MAJORRAM) ||
((minor(st.st_rdev)&0x7F) != 0) )
fatal("Ram disk close \"%s\" not mknod'ed properly", dvtmpcls);
if ( -1 == (tmp = open(dvtmpcls, 2)) )
fatal("Cannot open Ram Disk Close \"%s\"", dvtmpcls);
if ( close(tmp) < 0 )
fatal("Cannot close Ram Disk Close \"%s\"", dvtmpcls);
}
/*
* All actions for virtual array
*/
findblock(bp, action, odata)
long bp; /* data address */
enum vact action; /* what to do */
unsigned odata; /* optional data */
{
unsigned which, what_in, byte_no, bit;
unsigned long diskad;
unsigned char *byte;
extern long lseek();
switch(action) { /* use displacment to correct part of file */
case testBlock:
case markBlock:
case unmarkBlock:
bit = 1 << (bp & 7);
bp >>= 3;
case grabBlock: /* 8 at a time for copy */
assert(bp >= 0);
bp += blkdsp;
assert(bp < dupdsp);
break;
case testDup:
case markDup:
case unmarkDup:
bit = 1 << (bp & 7);
bp >>= 3;
case setDup: /* 8 at a time for copy */
assert(bp >= 0);
bp += dupdsp;
assert(bp < duplim);
break;
case Flags:
case setFlags:
case orFlags:
assert(bp > 0);
bp += flagdsp - 1;
assert(bp < blkdsp);
break;
case linkCtr:
case incLinkctr:
case setLinkctr:
assert(bp > 0);
bp--;
assert(bp < flagdsp);
}
byte_no = bp & (VBLK - 1);
bp >>= VBLKB;
which = bp & (MBKS - 1);
bp >>= MBKSB;
what_in = bp & 0x7fff;
if((diskad = map[which].what_in) != what_in) {
if(map[which].dirty) {
diskad <<= VBLKB + MBKSB;
diskad += which << VBLKB;
if(-1 == lseek(tmp, diskad, 0))
fatal("Error seeking tmp file");
if(VBLK != write(tmp, data[which], VBLK))
fatal("Error writing tmp file");
}
diskad = what_in;
diskad <<= VBLKB + MBKSB;
diskad += which << VBLKB;
if(-1 == lseek(tmp, diskad, 0))
fatal("Error seeking tmp file");
if(VBLK != read(tmp, data[which], VBLK))
memset(data[which], 0, VBLK);
map[which].what_in = what_in;
map[which].dirty = 0; /* clean */
}
byte = &data[which][byte_no];
switch(action) {
case testBlock:
case testDup:
return(*byte & bit);
case markBlock:
case markDup:
map[which].dirty = 1;
return(*byte |= bit);
case unmarkBlock:
case unmarkDup:
map[which].dirty = 1;
return(*byte ^= bit);
case linkCtr:
case Flags:
case grabBlock:
return(*byte);
case setLinkctr:
case setFlags:
case setDup:
map[which].dirty = 1;
return(*byte = odata);
case orFlags:
map[which].dirty = 1;
return(*byte |= odata);
case incLinkctr:
map[which].dirty = 1;
return(++*byte);
default:
fatal("Bad action in virtual system");
}
}
/*
* copy virtual memory blockmap to dupmap
* read and write groups to avoid possable thrashing.
*/
void
copyV(size)
unsigned size;
{
char buf[128];
register int i;
long bp, bs;
for(bs = bp = 0; bp < size; ) {
for(i = 0; (i < 128) && (bp < size); i++, bp++)
buf[i] = findblock(bp, grabBlock);
for(i = 0; (i < 128) && (bs < size); i++, bs++)
findblock(bs, setDup, buf[i]);
}
}
#ifdef TEST
fatal(s)
char *s;
{
fprintf(stderr, "%s\n", s);
exit(1);
}
static char buf[80];
gbuf()
{
if(NULL == gets(buf)) {
unlink("vtmp");
exit(0);
}
return(buf[0]);
}
main()
{
unsigned long b;
char data;
initV(10000, 10000, 20000);
for(;;) {
printf("b = block, d = dup, f = flags, l = linkctr\n");
switch(gbuf()) {
case 'l':
printf("s = set, d = display, i = increment: then loc\n");
gbuf();
sscanf(buf + 2, "%ld", &b);
switch(buf[0]) {
case 's':
setlinkctr(b, 0); /* no data */
case 'd':
printf("%d\n", linkctr(b));
break;
case 'i':
printf("%d\n", inclinkctr(b));
}
break;
case 'f':
printf("d = display, s = set, o = or: then loc\n");
gbuf();
sscanf(buf + 2, "%ld %c", &b, &data);
switch(buf[0]) {
case 's':
setflags(b, data);
case 'd':
break;
case 'o':
orflags(b, data);
}
printf("%c\n", flags(b));
break;
case 'b':
printf("t = test, m = mark, u = unmark: then loc\n");
gbuf();
sscanf(buf + 2, "%ld", &b);
switch(buf[0]) {
case 'm':
markblock(b);
case 't':
break;
case 'u':
unmarkblock(b);
}
printf("%c\n", testblock(b) ? '1' : '0');
break;
case 'd':
printf("t = test, m = mark, u = unmark: then loc\n");
gbuf();
sscanf(buf + 2, "%ld", &b);
switch(buf[0]) {
case 'm':
markdup(b);
case 't':
break;
case 'u':
unmarkdup(b);
}
printf("%c\n", testdup(b) ? '1' : '0');
break;
}
}
}
#endif
@
loc\n");
gbuf();
sscanf(buf + 2, "%ld", &b);
switch(buf[0]) {
case 'm':
markblock(b);
case 't':
break;
case 'u':
ufsck/READ_ME 644 3 3 1227 4664524112 5766 Ideas for improving the performance of fsck:
(1) Utilize a different mechanism for storing the (struct direct)
entries throughout phase2.c, to remove implicit memory intensive
redundancy.
(2) Encode the number of links per i-node count differently, in order
to save space taking advantage of the typical usage under Coherent.
(3) Arrange space for the tables in a total needed way to avoid later
fragmentation problems affecting the memory requests for successive
file systems.
(4) Devise a more clever buffering scheme for the blocks containing
i-nodes to understand the differences between phase1, phase2, and
phase4.
emove implicit memory intensive
redundancy.
(2) Encode the number of links per i-node count differently, in order
to save space taking advantage of the typical usage under Coherent.
(3) Arrange space for the tables in a total needed way to avoid later
fragmentation problems affecting the memory requests for successive
file systems.
(4fsck/cleanup.c 644 3 3 2324 4664524112 6541 /*
* Cleanup functions for phases of fsck
*/
#include "fsck.h"
cleanup()
{
int retval = 0;
if (sbpfix == TRUE)
writesuper();
prtstats();
if (changeflg == TRUE)
retval = advise();
close(fsfd);
cleanV();
return(retval);
}
writesuper()
{
register int i;
canshort(sbp->s_isize);
candaddr(sbp->s_fsize);
canshort(sbp->s_nfree);
for(i=0; i<NICFREE; i++)
candaddr(sbp->s_free[i]);
canshort(sbp->s_ninode);
for(i=0; i<NICINOD; i++)
canino(sbp->s_inode[i]);
cantime(sbp->s_time);
candaddr(sbp->s_tfree);
canino(sbp->s_tinode);
canshort(sbp->s_m);
canshort(sbp->s_n);
canlong(sbp->s_unique);
bwrite((daddr_t)SUPERI, sbp);
}
prtstats()
{
if (!fflag)
printf("%u files ", numfiles);
printf("%U blocks ", fsize - isize - totfree);
printf("%U free\n", totfree);
if ( lostsize ) {
lostsize = (lostsize + BSIZE - 1)/BSIZE;
printf("Expect roughly %U missing block%s next\n", lostsize,
(lostsize!=1) ? "s" : "" );
printf("time fsck is run as a result of inodes ");
printf("being cleared.\n");
}
}
advise()
{
int retval = 0;
printf(" ***** File System %s was modified *****\n", fsname);
if ( mounted ) {
printf(" ***** BOOT Coherent (NO SYNC!) *****\n");
retval = 1;
}
return(retval);
}
blocks ", fsize - isize - totfree);
printf("%U free\n", totfree);
if ( lostsize ) {
lostsize = (lostsize + BSIZE - 1)/BSIZE;
printf("Expect roughly %U missing block%s next\n", lostsize,
(lostsize!=1) ? "s" : "" );
printf("time fsck is run as a result of inodes ");
printf("being clearedfsck/fsck.h 644 3 3 14003 5033723044 6056 /*
* Header file for fsck -- File System Check Program
*
*/
#include <canon.h>
#include <sys/dir.h>
#include <sys/fblk.h>
#include <sys/filsys.h>
#include <sys/ino.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#if HPCOHERENT
typedef long fsize_t;
#endif
/*
* Conditional Compilation Flags
*/
#define NOT_ALL_ZERO_INODE /* Dependent on whether or not an inode */
#ifdef ALL_ZERO_INODE /* is totally zeroed when unallocated */
#undef ALL_ZERO_INODE /* or simply a zero mode and zero link */
#endif
/*
* Definitions and Externs
*/
#define NUL 0 /* true zero ! */
#define NULL ((char *)0)
#define YES 3 /* default actions */
#define NO 2
#define ASK 1
#define NFILSYS 10 /* max number of file systems */
#define MAXCH 20 /* max length of filesys name */
#define MAXBADOK 10 /* Max number of bad blocks before excessive */
extern int numbad; /* num bad blocks found so far this inode*/
#define MAXDUPOK 10 /* Max number of dup blocks */
/* in a single inode before excessive */
#define DUPTBLSIZE 20 /* Max number of dup referenced blocks */
extern daddr_t dupblck[]; /* table of duplicate referenced blocks */
extern int totdups; /* number of dup blocks found so far */
#define MAXBADFREE 10 /* max bad in free list before abort */
#define MAXDUPFREE 10 /* max dup in free list before abort */
#define GOOD 1 /* returned by bad() in util.c */
#define BAD 0
#define TRUE 1 /* errflag possibilities */
#define FALSE 0
extern int errflag; /* errflag indicates not to do phases */
#define OK 1 /* used to indicate excessive bad/dup */
#define STOP 0 /* blocks in an inode in phase1.c */
#define BAD_DUP 2
#define FIRSTIN 2 /* First real inode number */
#define ND 10 /* Number of Direct Blocks */
#undef NI
#define NI 1
#define NII 1
#define NIII 1
#undef NADDR
#define NADDR (ND+NI+NII+NIII)
extern int offsets[]; /* table of offsets for level of indirection */
/* for the blocks in an inode */
extern char nextchar(); /* used in util.c */
extern int fsfd; /* file system file descriptor */
extern int mdaction; /* default action for this invocation */
extern int daction; /* default action for current file system */
extern int writeflg; /* system write ok or read-only */
extern int qflag; /* quiet fsck flag */
extern int fflag; /* fast fsck flag */
extern int sflag; /* force free list salvation */
extern daddr_t fsize; /* file system size in blocks */
extern int isize; /* first block not in inode list */
/* isize is NOT unsigned so that comparisons */
/* with longs will not cast the long to */
/* unsigned thus producing confusing results */
extern daddr_t totfree; /* running count of total free blocks */
extern unsigned ninodes;/* Number of inodes in the files system */
extern char *fsname; /* file system name */
extern fsize_t pinfo(); /* returns size of file, in phase2.c */
extern ino_t lostfound(); /* returns inumber of lost+found dir */
extern struct dinode *ptrino(); /* returns a ptr to inode, give number */
extern char databuf[]; /* buffer to read in block, used throughout */
extern char buf2[]; /* alternate data buffer */
extern daddr_t cdbn; /* current block number, used by nextblock() */
#define DSIZE (sizeof(struct direct))
extern char *lostname; /* name of lost+found directory */
extern char *nameit(); /* nameing function for lost dirs and files */
extern int depth; /* used during tree traversal in phase2.c */
extern struct direct *path[]; /* used during tree traversal in phase2.c */
extern char *typename(); /* return string to type of inode */
extern struct filsys *sbp; /* Super Block */
extern int sbpfix; /* flag for super block fixes */
extern struct stat stats; /* used by statit() in util.c */
extern dev_t rootdev; /* root device number */
extern dev_t fsysrdev; /* file system real device number */
extern int mounted; /* flag indicating mountedness of filesystem */
extern int changeflg; /* file system modified flag */
extern int fixerup; /* flag to rebuild free list */
extern char *fixit; /* Prompt message phase[45].c */
extern int numfiles; /* num files in system */
extern daddr_t imap(); /* function for disk block mapping in util.c */
extern fsize_t lostsize; /* Size of files cleared in phase4.c */
extern char *tmpfile; /* TMP File name for virtual.c */
#define SUCCESS 1 /* used in connect() in phase3.c */
#define FAILURE 0
#define MODEMASK 0x07
#define ALLOCMASK 0x06
#define UNALLOC 0x00
#define UNKNOWN 0x01
#define IDIR 0x02
#define IREG 0x03
#define ICHR 0x04
#define IBLK 0x05
#define IPIPE 0x06
#define IBAD_IDUP 0x08
#define VISITED 0x10
#define UNREFDIR 0x20
#define CHILDDIR 0x40
#define IFREELIST 0x80
/*
* Macros for tables
*/
#define LOGNBPC 3 /* Log2 Number of Bits per Character */
/* Actions for virtual block system */
enum vact { testBlock, markBlock, unmarkBlock, grabBlock,
testDup, markDup, unmarkDup, setDup,
Flags, setFlags, orFlags,
linkCtr, incLinkctr, setLinkctr };
#define testblock(bn) findblock((unsigned long)(bn), testBlock)
#define markblock(bn) findblock((unsigned long)(bn), markBlock)
#define unmarkblock(bn) findblock((unsigned long)(bn), unmarkBlock)
#define testdup(bn) findblock((unsigned long)(bn), testDup)
#define markdup(bn) findblock((unsigned long)(bn), markDup)
#define unmarkdup(bn) findblock((unsigned long)(bn), unmarkDup)
#define flags(ino) findblock((unsigned long)(ino), Flags)
#define setflags(ino, data) findblock((unsigned long)(ino), setFlags, data)
#define orflags(ino, data) findblock((unsigned long)(ino), orFlags, data)
#define linkctr(ino) findblock((unsigned long)(ino), linkCtr)
#define inclinkctr(ino) findblock((unsigned long)(ino), incLinkctr)
#define setlinkctr(ino, data) findblock((unsigned long)(ino), setLinkctr, data)
#define badblks(ino) ( flags(ino)&IBAD_IDUP )
/*
* Miscellany
*/
#define NBPC 8 /* number of bits per character */
#define MAXINTN 255 /* used for interleave table */
/* in phase6.c */
/*
* Stdio Stuff
*/
#define putchar(c) { char b = c; write(1, &b, 1); }
extern char *malloc();
extern char *calloc();
findblock((unsigned long)(ino), linkCtr)
#define inclinkctr(ino) findblock((unsigned long)(ino), incLinkctr)
#define setlinkctr(ino, data) findblock((unsigned long)(ino), setLinkctr, data)
#define badblks(ino) ( flags(ino)&IBAD_IDUP )
/*
* Miscellany
*/
#define NBPC 8 /* number of bits per character */
#define MAXINTN 255 /* used for interleave table */
/* in phase6.c */
/*
* Stdio Stuff
*/
#define putchar(c) { char b = c; write(1, &b, 1); }
extern char *malloc();
extern char *calloc()fsck/init.c 644 3 3 12651 5041132573 6075 /*
* Perform initialization for phases of fsck
*/
#include "fsck.h"
#include <mnttab.h>
#include <mtab.h>
int fsfd; /* file system file descriptor */
int writeflg; /* write ok or read-only flag */
daddr_t fsize = SUPERI+1; /* file system size in blocks */
/* Allows for read of Super Block */
int isize; /* First block not in inode list */
daddr_t totfree; /* Running total free block count */
unsigned ninodes; /* number of inodes */
int numfiles; /* number of files in file system */
char superb[BSIZE]; /* Super Block */
struct filsys *sbp = superb;
int sbpfix; /* flag for super block fixes */
int offsets[] = /* table of offsets for the levels */
{ ND, ND+NI, ND+NI+NII, /* of indirection of blocks in the */
ND+NI+NII+NIII }; /* inode block list */
daddr_t dupblck[DUPTBLSIZE]; /* duplicate referenced blocks */
int totdups; /* number of dup blocks so far */
init()
{
int mode;
struct stat status;
unsigned short stmode;
mode = (mdaction == NO) ? 0 : 2;
if ( (fsfd = open(fsname, mode)) == (-1) ) {
mode = 0;
if ( (fsfd = open(fsname, mode)) == (-1) ) {
nonfatal("Can't open: %s", fsname);
return;
}
}
if (mode == 0) {
daction = NO;
writeflg = FALSE;
} else {
daction = mdaction;
writeflg = TRUE;
}
printf("%s: %s\n", fsname, (mode == 0) ? "(NO WRITE)" : "");
if ( fstat(fsfd, &status) == (-1) ) {
nonfatal("Can't stat: %s", fsname);
return;
}
stmode = status.st_mode & S_IFMT;
if ( (stmode != S_IFBLK) && (stmode != S_IFCHR) )
switch(query("file is not a block or character device; OK?")){
case YES:
break;
case NO:
errflag = TRUE;
return;
}
domount();
sbpfix = FALSE;
readsuper();
checksuper();
if ( !errflag )
alloctables();
}
/*
* Read in the super block and canonicalize
*/
readsuper()
{
register int i;
bread((daddr_t)SUPERI, superb);
sbp = superb;
canshort(sbp->s_isize);
candaddr(sbp->s_fsize);
canshort(sbp->s_nfree);
for(i=0; i<NICFREE; i++)
candaddr(sbp->s_free[i]);
canshort(sbp->s_ninode);
for(i=0; i<NICINOD; i++)
canino(sbp->s_inode[i]);
cantime(sbp->s_time);
candaddr(sbp->s_tfree);
canino(sbp->s_tinode);
canshort(sbp->s_m);
canshort(sbp->s_n);
canlong(sbp->s_unique);
}
/*
* Check super block for obvious inconsistencies
*/
checksuper()
{
fsize = sbp->s_fsize;
isize = sbp->s_isize;
totfree = fsize - isize;
if ( (isize<=INODEI) || (isize>=fsize) || (fsize<=INODEI) ) {
badsuper("Size check: fsize %U isize %u", fsize, isize);
errflag = TRUE;
}
if ( sbp->s_nfree > NICFREE )
badsuper("Too large free block count");
if ( sbp->s_ninode > NICINOD )
badsuper("Too large free i-node count");
}
/*
* Super Block Error Functions
*/
badsuper(x)
{
printf("%r\n", &x);
printf("fsck: %s: Bad Super Block: %u\n", fsname, SUPERI);
}
/*
* Allocate the necessary buffers for tables
*/
alloctables()
{
unsigned num, numl;
numl = 0;
if (!fflag) {
ninodes = (unsigned) (isize - INODEI) * INOPB;
numl = (unsigned) ninodes;
}
num = (unsigned) ((fsize+NBPC-1)/NBPC) * sizeof(char);
initV(numl, numl, num, num); /* virtual allocation */
numfiles = /* number of files in the file system */
totdups = 0; /* num dup blocks */
}
/*
* domount() checks the files /etc/mnttab and /etc/mtab to find
* out where the file system is mounted (if at all). It then
* reports where (and when if possible) it was last mounted.
*/
char *mnttab_name = "/etc/mnttab";
char *mtab_name = "/etc/mtab";
char *bttime_name = "/etc/boottime";
domount()
{
int fd;
struct mnttab mnttab;
struct mtab mtab;
register char *name;
struct stat sbuf;
time_t boottime;
int nothing();
char devname[MNTNSIZ+6] = "/dev/";
mounted = FALSE;
name = fsname; /* strip off all initial */
while (*name++ != '\0') ; /* directories in fsname */
while ( (*--name != '/') && (name>fsname) ) ;
if (*name == '/') name++;
if ( stat(bttime_name, &sbuf) == -1 )
boottime = (time_t)0;
else
boottime = sbuf.st_mtime;
if ( (fd=open(mnttab_name, 0)) != (-1) ) {
while ( read(fd, &mnttab, sizeof(mnttab))==sizeof(mnttab) )
if ( mnttab.mt_dev[0] && mnttab.mt_filsys[0] ) {
strncpy(&devname[5], mnttab.mt_filsys, MNTNSIZ);
devname[MNTNSIZ+5] = '\0';
statit(devname, nothing);
if (stats.st_rdev != fsysrdev)
continue;
statit(mnttab.mt_dev, nothing);
mounted = (stats.st_dev == fsysrdev);
prmnttab(&mnttab, boottime);
return;
}
}
if ( (fd=open(mtab_name, 0)) != (-1) ) {
while ( read(fd, &mtab, sizeof(mtab))==sizeof(mtab) )
if ( mtab.mt_name[0] && mtab.mt_special[0] ) {
strncpy(&devname[5], mtab.mt_special, MNAMSIZ);
devname[MNAMSIZ+5] = '\0';
statit(devname, nothing);
if (stats.st_rdev != fsysrdev)
continue;
statit(mtab.mt_name, nothing);
mounted = (stats.st_dev == fsysrdev);
prmtab(&mtab);
return;
}
}
if (fsysrdev == rootdev)
mounted = TRUE;
else
mounted = FALSE;
}
prmnttab(ptr, boottime)
struct mnttab *ptr;
time_t boottime;
{
if (mounted) {
if (boottime < ptr->mt_time)
boottime = ptr->mt_time;
printf("%s mounted on %.*s as of %s", fsname, MNTNSIZ,
ptr->mt_dev, ctime(&boottime));
} else
printf("%s unmounted. Last mounted on %.*s -- %s",
fsname, MNTNSIZ, ptr->mt_dev,
ctime(&ptr->mt_time));
}
prmtab(ptr)
struct mtab *ptr;
{
if (mounted)
printf("%s mounted on %.*s\n", fsname, MNAMSIZ, ptr->mt_name);
else
printf("%s unmounted. Last mounted on %.*s\n", fsname,
MNAMSIZ, ptr->mt_name);
}
nothing()
{}
) {
if (boottime < ptr->mt_time)
boottime = ptr->mt_time;
printf("%s mounted on fsck/is_fs.c 644 3 3 3467 4705135657 6236 #include <sys/stat.h>
#include <canon.h>
#include <sys/filsys.h>
/*
* Check if a special file is a well-formed filesystem.
* This routine is derived from code in "mount.c".
* Return values:
* -1 Not a device, cannot open, read or seek failed
* 0 No filesystem
* 1 Legal filesystem
*/
int
is_fs(special) char *special;
{
static struct filsys f;
struct stat sbuf;
register int fd;
register struct filsys *fp;
register daddr_t *dp;
register ino_t *ip, maxinode;
if (stat(special, &sbuf) < 0)
return -1; /* cannot stat device */
else if ((sbuf.st_mode&S_IFMT) != S_IFBLK
&& (sbuf.st_mode&S_IFMT) != S_IFCHR)
return -1; /* not a special file */
else if ((fd = open(special, 2)) < 0)
return -1; /* cannot open */
else if (lseek(fd, (long)SUPERI*BSIZE, 0) == -1L
|| read(fd, &f, sizeof(f)) != sizeof(f)) {
close(fd);
return -1; /* seek or read failed */
} else
close(fd); /* so far so good */
/* Canonical stuff. */
fp = &f;
canshort(fp->s_isize);
candaddr(fp->s_fsize);
canshort(fp->s_nfree);
for (dp = &fp->s_free[0]; dp < &fp->s_free[NICFREE]; dp += 1)
candaddr(*dp);
canshort(fp->s_ninode);
for (ip = &fp->s_inode[0]; ip < &fp->s_inode[NICINOD]; ip += 1)
canino(*ip);
candaddr(fp->s_tfree);
canino(fp->s_tinode);
/* Test for rationality. */
maxinode = (fp->s_isize - INODEI) * INOPB + 1;
if (fp->s_isize >= fp->s_fsize)
return 0;
if ((fp->s_tfree < fp->s_nfree)
|| (fp->s_tfree >= fp->s_fsize - fp->s_isize + 1))
return 0;
if ((fp->s_tinode < fp->s_ninode) || (fp->s_tinode >= maxinode-1 ))
return 0;
for (dp = &fp->s_free[0]; dp < &fp->s_free[fp->s_nfree]; dp += 1)
if ((*dp < fp->s_isize) || (*dp >= fp->s_fsize))
return 0;
for (ip = &fp->s_inode[0]; ip < &fp->s_inode[fp->s_ninode]; ip += 1)
if ((*ip < 1) || (*ip > maxinode))
return 0;
return 1;
}
- INODEI) * INOPB + 1;
if (fp->s_isize >= fp->s_fsize)
return 0;
if ((fp->s_tfree < fp->s_nfree)
|| (fp->s_tfree >= fp->s_fsize - fp->s_isize + 1))
return 0;
if ((fp->s_tinode < fp->s_ninode)fsck/link.c 644 3 3 2762 4664524116 6061 /*
* Routines to handle the counting of links for each i-node
*/
#include "fsck.h"
linkincr(inum)
ino_t inum;
{
if (inclinkctr(inum) == 0 )
fatal("Too many links in i-node, %d", inum);
}
/*
* The following is the beginning of thinking of how to change
* the number of bits used in the link count tables from 8-per
* i-node to 2-per i-node, with additional tables for those
* i-nodes with more than 2 links. The changes would be to the
* definition of i_lnks, the macro linkctr(), the function linkincr(),
* and in init.c, the allocation of table space.
*/
#ifdef NEWLINKSTUFFF
char *linkmap; /* table of inodes with one link */
#define testlink(in) ( linkmap[((unsigned)bn)>>(LOGNBPC-1)] & \
3 << (((unsigned)bn)&(NBPC>>1)) )
#define marklink(in) ( linkmap[((unsigned)bn)>>(LOGNBPC-1)] |= \
1 << (((unsigned)bn)&(NBPC-2)) )
#define unmarklink(in) ( linkmap[((unsigned)bn)>>(LOGNBPC-1)] ^= \
1 << (((unsigned)bn)&(NBPC-2)) )
linkcntr(inum)
ino_t inum;
{
index = ((unsigned) inum) >> (LOGNBPC-1) ;
distance = ((unsigned) inum) & ((NBPC>>1) - 1) ;
mask = 3 << distance;
answer = ( linkmap[index] & mask ) >> distance;
if ( answer < 3 )
return(answer);
hash = inum & 0xFF;
bucket = &linktable[hash];
bktinum = bucket->inumb;
if ( bktinum == inum ) {
answer = bucket->numlink;
if ( answer == 0xFF )
return( bigcntr(inum) );
else
return( answer + 3 );
}
if ( bktinum > inum )
fatal("internal linktable corruption.");
}
linkincr(inum)
ino_t inum;
{
}
#endif
num) >> (LOGNBfsck/main.c 644 3 3 12436 5041134504 6053 /*
* fsck -- File System Check Program
* an interactive file system check and repair program.
*
* Usage:
* /etc/fsck [-y] [-n] [-q] [-f] [-{sS}] [-t TMPFILE] [filesystem ...]
* audit and interactively repair inconsistent conditions for
* file systems. Options -y and -n indicate an assumed response
* to all questions asked by fsck. Default is to prompt operator
* for yes/no response. Option -q is to quiet fsck from printing
* certain messages, i.e. no size check messages, unreferenced
* pipes will be silently removed, and counts in the superblock
* will be automatically fixed and free list salvaged, if necessary.
* Option -f is for a 'fast' check of the file system, i.e. only
* check blocks, sizes, superblock counts, and the free list.
* (-f) does not check pathnames, connectivity, or reference
* counts. Option -s forces the reconstruction (or salvaging) of
* both the free inode list and the free block list, even if there
* are no file system problems. This will reorder the free block
* list in the best order to limit additional fragmentation (respecting
* interleaving as well). Note: Option -s will be ignored on mounted
* file systems. The option -S acts in the same manner as -s except
* that it will not be ignored on mounted file systems. Beware: -S
* on mounted file systems should only be used if you intend to reboot
* NO SYNC immediately afterwards. Option -t sets the temporary file
* to use for disk caching of necessary tables on filesystems which are
* too big to do in core. The temporary file defaults to "/dev/rram1",
* which must be there.
*/
#include "fsck.h"
int errflag;
int mdaction; /* default action for invocation */
int daction; /* default action for file system */
int gSflag=FALSE; /* force salvage flag ignored mounted */
int gsflag=FALSE; /* force salvage flag ignored mounted */
int sflag=FALSE; /* force salvage flag */
int qflag=FALSE; /* fsck quiet flag */
int fflag=FALSE; /* fsck fast flag */
char *tmpfile = NULL; /* TMP file for virtual.c */
char *checklistfile = "/etc/checklist"; /* default file for list of file */
/* systems to fsck. */
char *filelist[NFILSYS]; /* list of filesystems */
char word[MAXCH]; /* hold single words */
char *fsname; /* file system name */
dev_t rootdev; /* root device number */
dev_t fsysrdev; /* file system real device number */
int mounted; /* flag for mounted file system */
int changeflg; /* file system modified flag */
main(argc, argv)
char *argv[];
{
int yflag=0, nflag=0;
int retval;
while (argc>1 && *argv[1]=='-') {
switch (argv[1][1]) {
case 'q':
qflag = TRUE;
break;
case 'y':
yflag = 1;
break;
case 'n':
nflag = 1;
break;
case 'f':
fflag = TRUE;
break;
case 'S':
gSflag = TRUE;
break;
case 's':
gsflag = TRUE;
break;
case 't':
tmpfile = argv[2];
argc--;
argv++;
break;
default:
usage();
break;
}
argc--;
argv++;
}
if ( yflag+nflag > 1 )
usage();
mdaction = ( yflag ? YES :
nflag ? NO : ASK );
if ( argc > 1 )
retval = allfsck(argv+1);
else {
getlist();
retval = allfsck(filelist);
}
exit(retval);
}
/*
* perform fsck on each of the individual filesystem in list
*/
allfsck(fsl)
register char **fsl;
{
int fatal();
int retval = 0;
sync();
statit("/", fatal);
rootdev = stats.st_dev;
while (*fsl != NULL)
retval |= fsck(*fsl++);
return(retval);
}
/*
* get the names of the filesystems from the default file
* checklistfile (e.g. /etc/checklist)
*/
getlist()
{
int fd;
int index, size;
if ( (fd = open(checklistfile, 0)) == (-1) )
fatal("Can't open checklist file: %s", checklistfile);
index = 0;
while ( ((size = getword(fd)) != 0) && (index < NFILSYS) ) {
filelist[index] = malloc( size );
strcpy(filelist[index++], word);
}
if (size != 0)
fatal("Too many file systems in checklist file: %s",
checklistfile);
filelist[index] = NULL;
close(fd);
}
/*
* read in the next "word" from file with descriptor fd
* return the length of the word.
*/
getword(fd)
int fd;
{
int n = 0, num;
char *cp = word;
char ch;
while ( ( (num=read(fd, &ch, 1)) == 1 ) &&
( (ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r') ) );
if (num != 1)
return(0);
do {
*cp++ = ch;
} while ( (++n < MAXCH) && (read(fd, &ch, 1) == 1) &&
(ch != ' ') && (ch != '\t') && (ch != '\n') && (ch != '\r') );
*cp = '\0';
return(n+1);
}
/*
* perform fsck on the given filesystem
*/
fsck(name)
char *name;
{
int retval = 1;
int nonfatal();
fsname = name; /* file system name */
errflag = FALSE;
statit(fsname, nonfatal);
fsysrdev = stats.st_rdev;
if ( errflag )
return(retval);
changeflg = FALSE;
init();
if ( sflag = ((gsflag && !mounted) || gSflag) )
printf("Switch \"-s\" selected to automatically rebuild free lists\n");
if (!sflag && gsflag)
printf("Ignoring \"-s\" on mounted file system\n");
if ( !errflag ) {
phase1(); /* check blocks and sizes */
if ( !fflag ) {
phase2(); /* check pathnames */
phase3(); /* check connectivity */
phase4(); /* check reference counts */
}
phase5(); /* check free list */
phase6(); /* salvage free list */
retval = cleanup();
}
return(retval);
}
usage()
{
printf("\
Usage: /etc/fsck [-y] [-n] [-q] [-f] [-{sS}] [-t TMPFILE] [filesystem ...]\n");
_exit(1);
}
sflag && gsflag)
printf("Ignoring \"-s\" on mounted file system\n");
if ( !errflag ) {
phase1(); /* check blocks and sizes */
if ( !fflag ) {
phase2(); /* check pathnames */
phase3(); /* check connectivity fsck/objects/ 755 3 3 0 5045007474 6312 fsck/objects/main.o 644 3 3 4453 5045007122 7477 0 p IVW� �F� �F� �~� �v
�|�=-t� �~
�}�E��B � CC.;��u`.�gS f n q s t y ~ v o ` � � h �6 �;�F� �4�F� �-�8 �%�0 ��2 ��~
�E�:�N�F
��r�N�F
�c��F�F�= ~�Z�~� t� ��~� t� �� � �~~�F
@@P��X h � ���F�P�����_^�VW� �v�F� ���h hM������ � �<