static char *sccsid
= "@(#)main.c 1.20 (Berkeley) %G%";
typedef int (*SIG_TYP
)();
#define NDIRECT(fs) ((fs)->fs_bsize / sizeof(struct direct))
#define MAXNDIRECT (MAXBSIZE / sizeof(struct direct))
#define MAXNINDIR (MAXBSIZE / sizeof (daddr_t))
#define MAXINOPB (MAXBSIZE / sizeof (struct dinode))
#define SPERB (MAXBSIZE / sizeof(short))
#define MAXDUP 10 /* limit on dup blks (per inode) */
#define MAXBAD 10 /* limit on bad blks (per inode) */
#define USTATE 0 /* inode not allocated */
#define FSTATE 01 /* inode is file */
#define DSTATE 02 /* inode is directory */
#define CLEAR 03 /* inode is to be cleared */
typedef struct dinode DINODE
;
typedef struct direct DIRECT
;
#define ALLOC ((dp->di_mode & IFMT) != 0)
#define DIR ((dp->di_mode & IFMT) == IFDIR)
#define REG ((dp->di_mode & IFMT) == IFREG)
#define BLK ((dp->di_mode & IFMT) == IFBLK)
#define CHR ((dp->di_mode & IFMT) == IFCHR)
#define MPC ((dp->di_mode & IFMT) == IFMPC)
#define MPB ((dp->di_mode & IFMT) == IFMPB)
#define SPECIAL (BLK || CHR || MPC || MPB)
ino_t startinum
; /* blk num of first in raw area */
struct bufarea
*b_next
; /* must be first */
char b_buf
[MAXBSIZE
]; /* buffer space */
short b_lnks
[SPERB
]; /* link counts */
daddr_t b_indir
[MAXNINDIR
]; /* indirect block */
struct fs b_fs
; /* super block */
struct cg b_cg
; /* cylinder group */
struct dinode b_dinode
[MAXINOPB
]; /* inode block */
DIRECT b_dir
[MAXNDIRECT
]; /* directory */
typedef struct bufarea BUFAREA
;
BUFAREA inoblk
; /* inode blocks */
BUFAREA fileblk
; /* other blks in filesys */
BUFAREA sblk
; /* file system superblock */
#define initbarea(x) (x)->b_dirty = 0;(x)->b_bno = (daddr_t)-1
#define dirty(x) (x)->b_dirty = 1
#define inodirty() inoblk.b_dirty = 1
#define sbdirty() sblk.b_dirty = 1
#define cgdirty() cgblk.b_dirty = 1
#define dirblk fileblk.b_un
#define sblock sblk.b_un.b_fs
#define cgrp cgblk.b_un.b_cg
} dfile
; /* file descriptors for filesys */
#define DUPTBLSIZE 100 /* num of dup blocks to remember */
daddr_t duplist
[DUPTBLSIZE
]; /* dup block table */
daddr_t
*enddup
; /* next entry in dup table */
daddr_t
*muldup
; /* multiple dups part of table */
#define MAXLNCNT 20 /* num zero link cnts to remember */
ino_t badlncnt
[MAXLNCNT
]; /* table of inos with zero link cnts */
ino_t
*badlnp
; /* next entry in table */
char nflag
; /* assume a no response */
char yflag
; /* assume a yes response */
int bflag
; /* location of alternate super block */
int debug
; /* output debugging info */
char preen
; /* just fix normal inconsistencies */
char rplyflag
; /* any questions asked? */
char hotroot
; /* checking root device */
char fixcg
; /* corrupted free list bit maps */
char *blkmap
; /* ptr to primary blk allocation map */
char *freemap
; /* ptr to secondary blk allocation map */
char *statemap
; /* ptr to inode state table */
short *lncntp
; /* ptr to link count table */
char *pathp
; /* pointer to pathname position */
char *thisname
; /* ptr to current pathname component */
char *srchname
; /* name being searched for in dir */
char *lfname
= "lost+found";
ino_t inum
; /* inode we are currently working on */
ino_t imax
; /* number of inodes */
ino_t parentdir
; /* i number of parent directory */
ino_t lastino
; /* hiwater mark of inodes */
ino_t lfdir
; /* lost & found directory */
ino_t orphan
; /* orphaned inode */
off_t filsize
; /* num blks seen in file */
off_t maxblk
; /* largest logical blk in file */
off_t bmapsz
; /* num chars in blkmap */
daddr_t n_ffree
; /* number of small free blocks */
daddr_t n_bfree
; /* number of large free blocks */
daddr_t n_blks
; /* number of blocks used */
daddr_t n_files
; /* number of files seen */
daddr_t fmax
; /* number of blocks in the volume */
#define zapino(x) (*(x) = zino)
#define setlncnt(x) (lncntp[inum] = x)
#define getlncnt() (lncntp[inum])
#define declncnt() (--lncntp[inum])
#define setbmap(x) setbit(blkmap, x)
#define getbmap(x) isset(blkmap, x)
#define clrbmap(x) clrbit(blkmap, x)
#define setfmap(x) setbit(freemap, x)
#define getfmap(x) isset(freemap, x)
#define clrfmap(x) clrbit(freemap, x)
#define setstate(x) (statemap[inum] = x)
#define getstate() statemap[inum]
int pass1(), pass1b(), pass2(), pass4(), pass5();
char *rawname(), *rindex(), *unrawname();
extern int inside
[], around
[];
extern unsigned char *fragtbl
[];
int pid
, passno
, anygtr
, sumstatus
;
while (--argc
> 0 && **++argv
== '-') {
printf("Alternate super block location: %d\n", bflag
);
case 'n': /* default no answer flag */
case 'y': /* default yes answer flag */
errexit("%c option?\n", **argv
);
if (signal(SIGINT
, SIG_IGN
) != SIG_IGN
)
errexit("Can't open checklist file: %s\n", FSTAB
);
while ((fsp
= getfsent()) != 0) {
if (strcmp(fsp
->fs_type
, FSTAB_RW
) &&
strcmp(fsp
->fs_type
, FSTAB_RO
))
passno
== 1 && fsp
->fs_passno
== passno
) {
if (blockcheck(fsp
->fs_spec
) == 0 && preen
)
} else if (fsp
->fs_passno
> passno
)
else if (fsp
->fs_passno
== passno
) {
if (blockcheck(fsp
->fs_spec
)==0)
while (wait(&status
) != -1)
struct ostat stslash
, stblock
, stchar
;
if (stat("/", &stslash
) < 0){
error("Can't stat root\n");
if (stat(name
, &stblock
) < 0){
error("Can't stat %s\n", name
);
if (stblock
.st_mode
& S_IFBLK
) {
if (stat(raw
, &stchar
) < 0){
error("Can't stat %s\n", raw
);
if (stchar
.st_mode
& S_IFCHR
) {
if (stslash
.st_dev
== stblock
.st_rdev
) {
error("%s is not a character device\n", raw
);
} else if (stblock
.st_mode
& S_IFCHR
) {
error("Can't make sense out of name %s\n", name
);
error("Can't make sense out of name %s\n", name
);
char *dp
= rindex(cp
, '/');
if ((stb
.st_mode
&S_IFMT
) != S_IFCHR
)
char *dp
= rindex(cp
, '/');
pfatal("CAN'T CHECK DEVICE.");
printf("** Root file system\n");
printf("** Phase 1 - Check Blocks and Sizes\n");
n_blks
+= howmany(sblock
.fs_cssize
, sblock
.fs_bsize
) * sblock
.fs_frag
;
for (c
= 0; c
< sblock
.fs_ncg
; c
++) {
if (getblk(&cgblk
, cgtod(&sblock
, c
), sblock
.fs_cgsize
) == 0)
for (i
= 0; i
< sblock
.fs_ipg
; i
++, inum
++) {
if (!isset(cgrp
.cg_iused
, i
)) {
printf("%d bad, not used\n",
pfatal("UNKNOWN FILE TYPE I=%u", inum
);
if (reply("CLEAR") == 1) {
if (setlncnt(dp
->di_nlink
) <= 0) {
if (badlnp
< &badlncnt
[MAXLNCNT
])
pfatal("LINK COUNT TABLE OVERFLOW");
if (reply("CONTINUE") == 0)
setstate(DIR ? DSTATE
: FSTATE
);
badblk
= dupblk
= 0; filsize
= 0; maxblk
= 0;
if (DIR && dp
->di_size
% sizeof(DIRECT
)) {
pwarn("DIRECTORY MISALIGNED I=%u\n",
if (isset(cgrp
.cg_iused
, i
)) {
printf("%d bad, marked used\n",
pfatal("PARTIALLY ALLOCATED INODE I=%u", inum
);
if (reply("CLEAR") == 1) {
if (n
!= cgrp
.cg_cs
.cs_nifree
) {
printf("cg[%d].cg_cs.cs_nifree is %d not %d\n",
c
, cgrp
.cg_cs
.cs_nifree
, n
);
if (enddup
!= &duplist
[0]) {
pfatal("INTERNAL ERROR: dups with -p");
printf("** Phase 1b - Rescan For More DUPS\n");
for (c
= 0; c
< sblock
.fs_ncg
; c
++) {
for (i
= 0; i
< sblock
.fs_ipg
; i
++, inum
++) {
if (getstate() != USTATE
&&
(ckinode(dp
, ADDR
) & STOP
))
printf("** Phase 2 - Check Pathnames\n");
thisname
= pathp
= pathname
;
errexit("ROOT INODE UNALLOCATED. TERMINATING.\n");
pfatal("ROOT INODE NOT DIRECTORY");
if (reply("FIX") == 0 || (dp
= ginode()) == NULL
)
pfatal("DUPS/BAD IN ROOT INODE");
if (reply("CONTINUE") == 0)
printf("** Phase 3 - Check Connectivity\n");
for (inum
= ROOTINO
; inum
<= lastino
; inum
++) {
if (getstate() == DSTATE
) {
if ((dp
= ginode()) == NULL
)
if ((inum
= parentdir
) == 0)
} while (getstate() == DSTATE
);
thisname
= pathp
= pathname
;
printf("** Phase 4 - Check Reference Counts\n");
for (inum
= ROOTINO
; inum
<= lastino
; inum
++) {
for (blp
= badlncnt
;blp
< badlnp
; blp
++)
if (imax
- ROOTINO
- n_files
!= sblock
.fs_cstotal
.cs_nifree
) {
pwarn("FREE INODE COUNT WRONG IN SUPERBLK");
if (preen
|| reply("FIX") == 1) {
sblock
.fs_cstotal
.cs_nifree
= imax
- n_files
;
printf("** Phase 5 - Check Cyl groups\n");
copy(blkmap
, freemap
, (unsigned)bmapsz
);
n_index
= sblock
.fs_ncg
* (cgdmin(&sblock
, 0) - cgtod(&sblock
, 0));
for (c
= 0; c
< sblock
.fs_ncg
; c
++) {
daddr_t cbase
= cgbase(&sblock
, c
);
for (n
= 0; n
< sblock
.fs_cpg
; n
++) {
for (i
= 0; i
< NRPOS
; i
++)
for (i
= 0; i
< sblock
.fs_frag
; i
++) {
* need to account for the spare boot and super blocks
* which appear (inaccurately) bad
n_bad
+= cgtod(&sblock
, c
) - cbase
;
if (getblk(&cgblk
, cgtod(&sblock
, c
), sblock
.fs_cgsize
) == 0)
for (b
= 0; b
< sblock
.fs_fpg
; b
+= sblock
.fs_frag
) {
if (isblock(&sblock
, cgrp
.cg_free
, b
/sblock
.fs_frag
)) {
if (pass5(cbase
+b
, sblock
.fs_frag
) == STOP
)
n_ffree
-= sblock
.fs_frag
;
botot
[cbtocylno(&sblock
, b
)]++;
bo
[cbtocylno(&sblock
, b
)]
[cbtorpos(&sblock
, b
)]++;
for (d
= 0; d
< sblock
.fs_frag
; d
++)
if (isset(cgrp
.cg_free
, b
+d
))
if (pass5(cbase
+b
+d
,1) == STOP
)
blk
= ((cgrp
.cg_free
[b
/ NBBY
] >> (b
% NBBY
)) &
(0xff >> (NBBY
- sblock
.fs_frag
)));
fragacct(&sblock
, blk
, frsum
, 1);
for (i
= 0; i
< sblock
.fs_frag
; i
++) {
if (cgrp
.cg_frsum
[i
] != frsum
[i
]) {
printf("cg[%d].cg_frsum[%d] have %d calc %d\n",
c
, i
, cgrp
.cg_frsum
[i
], frsum
[i
]);
for (n
= 0; n
< sblock
.fs_cpg
; n
++) {
if (botot
[n
] != cgrp
.cg_btot
[n
]) {
printf("cg[%d].cg_btot[%d] have %d calc %d\n",
c
, n
, cgrp
.cg_btot
[n
], botot
[n
]);
for (i
= 0; i
< NRPOS
; i
++)
if (bo
[n
][i
] != cgrp
.cg_b
[n
][i
]) {
printf("cg[%d].cg_b[%d][%d] have %d calc %d\n",
c
, n
, i
, cgrp
.cg_b
[n
][i
],
pwarn("%d DUP BLKS IN BIT MAPS\n", dupblk
);
if ((b
= n_blks
+n_ffree
+sblock
.fs_frag
*n_bfree
+n_index
+n_bad
) != fmax
) {
pwarn("%ld BLK(S) MISSING\n", fmax
- b
);
} else if (inosumbad
+ offsumbad
+ frsumbad
) {
pwarn("SUMMARY INFORMATION %s%s%sBAD\n",
inosumbad
? "(INODE FREE) " : "",
offsumbad
? "(BLOCK OFFSETS) " : "",
frsumbad
? "(FRAG SUMMARIES) " : "");
} else if (n_ffree
!= sblock
.fs_cstotal
.cs_nffree
||
n_bfree
!= sblock
.fs_cstotal
.cs_nbfree
) {
pwarn("FREE BLK COUNT(S) WRONG IN SUPERBLK");
if (preen
|| reply("FIX") == 1) {
sblock
.fs_cstotal
.cs_nffree
= n_ffree
;
sblock
.fs_cstotal
.cs_nbfree
= n_bfree
;
pwarn("BAD CYLINDER GROUPS");
else if (reply("SALVAGE") == 0)
printf("** Phase 6 - Salvage Cylinder Groups\n");
n_ffree
= sblock
.fs_cstotal
.cs_nffree
;
n_bfree
= sblock
.fs_cstotal
.cs_nbfree
;
pwarn("%d files, %d used, %d free (%d frags, %d blocks)\n",
n_files
, n_blks
- howmany(sblock
.fs_cssize
, sblock
.fs_bsize
) * sblock
.fs_frag
,
n_ffree
+ sblock
.fs_frag
* n_bfree
, n_ffree
, n_bfree
);
if (dfile
.mod
&& hotroot
) {
printf("\n***** BOOT UNIX (NO SYNC!) *****\n");
if (dfile
.mod
&& preen
== 0)
printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
* An inconsistency occured which shouldn't during normal operations.
* Die if preening, otw just printf.
printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", devname
);
* Pwarn is like printf when not preening,
* or a warning (preceded by filename) when preening.
pwarn(s
, a1
, a2
, a3
, a4
, a5
)
printf(s
, a1
, a2
, a3
, a4
, a5
);
int (*func
)(), n
, ndb
, size
;
func
= (flg
== ADDR
) ? pfunc
: dirscan
;
ndb
= howmany(dp
->di_size
, sblock
.fs_bsize
);
for (ap
= &dp
->di_db
[0]; ap
< &dp
->di_db
[NDADDR
]; ap
++) {
if (--ndb
== 0 && (dp
->di_size
% sblock
.fs_bsize
))
size
= howmany(dp
->di_size
% sblock
.fs_bsize
, sblock
.fs_fsize
);
if (*ap
&& (ret
= (*func
)(*ap
, size
)) & STOP
)
for (ap
= &dp
->di_ib
[0], n
= 1; n
<= 2; ap
++, n
++) {
if (*ap
&& (ret
= iblock(*ap
, n
, flg
, dp
->di_size
- sblock
.fs_bsize
* NDADDR
)) & STOP
)
iblock(blk
, ilevel
, flg
, isize
)
if (((n
= (*func
)(blk
, sblock
.fs_frag
)) & KEEPON
) == 0)
if (outrange(blk
)) /* protect thyself */
if (getblk(&ib
, blk
, sblock
.fs_bsize
) == NULL
)
nif
= isize
/ sblock
.fs_bsize
+ 1;
} else /* ilevel == 1 */ {
nif
= isize
/ (sblock
.fs_bsize
* NINDIR(&sblock
)) + 1;
if (nif
> NINDIR(&sblock
))
aplim
= & ib
.b_un
.b_indir
[nif
];
for (ap
= ib
.b_un
.b_indir
, i
= 1; ap
< aplim
; ap
++, i
++)
n
= iblock(*ap
, ilevel
, flg
, isize
- i
* NINDIR(&sblock
) * sblock
.fs_bsize
);
n
= (*func
)(*ap
, sblock
.fs_frag
);
for (; size
> 0; blk
++, size
--) {
if (++badblk
>= MAXBAD
) {
printf("EXCESSIVE BAD BLKS I=%u", inum
);
if (reply("CONTINUE") == 0)
} else if (getbmap(blk
)) {
if (++dupblk
>= MAXDUP
) {
printf("EXCESSIVE DUP BLKS I=%u", inum
);
if (reply("CONTINUE") == 0)
if (enddup
>= &duplist
[DUPTBLSIZE
]) {
printf("DUP TABLE OVERFLOW.");
if (reply("CONTINUE") == 0)
for (dlp
= duplist
; dlp
< muldup
; dlp
++)
for (; size
> 0; blk
++, size
--) {
for (dlp
= duplist
; dlp
< muldup
; dlp
++)
if ((inum
= dirp
->d_ino
) == 0)
for (p
= dirp
->d_name
; p
< &dirp
->d_name
[DIRSIZ
]; )
if ((*pathp
++ = *p
++) == 0) {
if (inum
> imax
|| inum
<= 0)
n
= direrr("I OUT OF RANGE");
n
= direrr("UNALLOCATED");
if ((n
= direrr("DUP/BAD")) == 1)
if ((dp
= ginode()) == NULL
)
setstate(DIR ? DSTATE
: FSTATE
);
for (; size
> 0; blk
++, size
--) {
for (dlp
= duplist
; dlp
< enddup
; dlp
++)
for (; size
> 0; blk
++, size
--) {
pfatal("BAD BLOCKS IN BIT MAPS.");
if (++badblk
>= MAXBAD
) {
printf("EXCESSIVE BAD BLKS IN BIT MAPS.");
if (reply("CONTINUE") == 0)
} else if (getfmap(blk
)) {
if (++dupblk
>= DUPTBLSIZE
) {
printf("EXCESSIVE DUP BLKS IN BIT MAPS.");
if (reply("CONTINUE") == 0)
if (blk
>= fmax
|| blk
< cgdmin(&sblock
, c
)) {
pfatal("%ld %s I=%u", blk
, s
, inum
);
setstate(CLEAR
); /* mark for possible clearing */
if ((dp
= ginode()) == NULL
)
filsize
-= sblock
.fs_bsize
;
edirp
= &dirblk
.b_dir
[NDIRECT(&sblock
)*nf
/sblock
.fs_frag
];
for (dirp
= dirblk
.b_dir
; dirp
< edirp
&&
filsize
> 0; dirp
++, filsize
-= sizeof(DIRECT
)) {
if (getblk(&fileblk
, blk
, nf
* sblock
.fs_fsize
) == NULL
) {
filsize
-= (&dirblk
.b_dir
[NDIRECT(&sblock
)]-dirp
)*sizeof(DIRECT
);
p1
= &dirp
->d_name
[DIRSIZ
];
p2
= &direntry
.d_name
[DIRSIZ
];
while (p1
> (char *)dirp
)
if ((n
= (*pfunc
)(&direntry
)) & ALTERD
) {
if (getblk(&fileblk
, blk
, nf
* sblock
.fs_fsize
) != NULL
) {
p1
= &dirp
->d_name
[DIRSIZ
];
p2
= &direntry
.d_name
[DIRSIZ
];
while (p1
> (char *)dirp
)
return (filsize
> 0 ? KEEPON
: STOP
);
if ((dp
= ginode()) != NULL
&& ftypeok(dp
))
pfatal("%s=%s", DIR?"DIR":"FILE", pathname
);
pfatal("NAME=%s", pathname
);
return (reply("REMOVE"));
if ((dp
= ginode()) == NULL
)
if (dp
->di_nlink
== lcnt
) {
(lfdir
==inum
)?lfname
:(DIR?"DIR":"FILE"));
printf(" COUNT %d SHOULD BE %d",
dp
->di_nlink
, dp
->di_nlink
-lcnt
);
if (preen
|| reply("ADJUST") == 1) {
if ((dp
= ginode()) == NULL
)
pwarn("%s %s", s
, DIR?"DIR":"FILE");
if (preen
|| reply("CLEAR") == 1) {
int super
= bflag
? bflag
: SBLOCK
;
if (stat("/", &statb
) < 0)
errexit("Can't stat root\n");
if (stat(dev
, &statb
) < 0) {
error("Can't stat %s\n", dev
);
if ((statb
.st_mode
& S_IFMT
) == S_IFBLK
)
else if ((statb
.st_mode
& S_IFMT
) == S_IFCHR
)
if (reply("file is not a block or character device; OK") == 0)
if (rootdev
== statb
.st_rdev
)
if ((dfile
.rfdes
= open(dev
, 0)) < 0) {
error("Can't open %s\n", dev
);
if (nflag
|| (dfile
.wfdes
= open(dev
, 1)) < 0) {
pfatal("NO WRITE ACCESS");
fixcg
= 0; inosumbad
= 0; offsumbad
= 0; frsumbad
= 0;
n_files
= n_blks
= n_ffree
= n_bfree
= 0;
muldup
= enddup
= &duplist
[0];
if (bread(&dfile
, &sblock
, super
, SBSIZE
) == 0)
* run a few consistency checks of the super block
if (sblock
.fs_magic
!= FS_MAGIC
)
{ badsb("MAGIC NUMBER WRONG"); return (0); }
{ badsb("NCG OUT OF RANGE"); return (0); }
if (sblock
.fs_cpg
< 1 || sblock
.fs_cpg
> MAXCPG
)
{ badsb("CPG OUT OF RANGE"); return (0); }
{ badsb("NSECT < 1"); return (0); }
{ badsb("NTRAK < 1"); return (0); }
if (sblock
.fs_spc
!= sblock
.fs_nsect
* sblock
.fs_ntrak
)
{ badsb("SPC DOES NOT JIVE w/NTRAK*NSECT"); return (0); }
if (sblock
.fs_ipg
% INOPB(&sblock
))
{ badsb("INODES NOT MULTIPLE OF A BLOCK"); return (0); }
if (cgdmin(&sblock
, 0) >= sblock
.fs_cpg
* sblock
.fs_spc
/ NSPF(&sblock
))
{ badsb("IMPLIES MORE INODE THAN DATA BLOCKS"); return (0); }
if (sblock
.fs_ncg
* sblock
.fs_cpg
< sblock
.fs_ncyl
||
(sblock
.fs_ncg
- 1) * sblock
.fs_cpg
>= sblock
.fs_ncyl
)
{ badsb("NCYL DOES NOT JIVE WITH NCG*CPG"); return (0); }
if (sblock
.fs_fpg
!= sblock
.fs_cpg
* sblock
.fs_spc
/ NSPF(&sblock
))
{ badsb("FPG DOES NOT JIVE WITH CPG & SPC"); return (0); }
if (sblock
.fs_size
* NSPF(&sblock
) <=
(sblock
.fs_ncyl
- 1) * sblock
.fs_spc
)
{ badsb("SIZE PREPOSTEROUSLY SMALL"); return (0); }
if (sblock
.fs_size
* NSPF(&sblock
) > sblock
.fs_ncyl
* sblock
.fs_spc
)
{ badsb("SIZE PREPOSTEROUSLY LARGE"); return (0); }
/* rest we COULD repair... */
if (sblock
.fs_sblkno
!= SBLOCK
)
{ badsb("SBLKNO CORRUPTED"); return (0); }
roundup(howmany(BBSIZE
+ SBSIZE
, sblock
.fs_fsize
), sblock
.fs_frag
))
{ badsb("CBLKNO CORRUPTED"); return (0); }
if (sblock
.fs_iblkno
!= sblock
.fs_cblkno
+ sblock
.fs_frag
)
{ badsb("IBLKNO CORRUPTED"); return (0); }
sblock
.fs_iblkno
+ sblock
.fs_ipg
/ INOPF(&sblock
))
{ badsb("DBLKNO CORRUPTED"); return (0); }
roundup(sizeof(struct cg
) + howmany(sblock
.fs_fpg
, NBBY
),
{ badsb("CGSIZE INCORRECT"); return (0); }
if (sblock
.fs_cssize
!= sblock
.fs_ncg
* sizeof(struct csum
))
{ badsb("CSSIZE INCORRECT"); return (0); }
imax
= sblock
.fs_ncg
* sblock
.fs_ipg
;
* allocate the necessary maps
bmapsz
= roundup(howmany(fmax
, NBBY
), sizeof(short));
blkmap
= (char *)calloc(bmapsz
, sizeof (char));
freemap
= (char *)calloc(bmapsz
, sizeof (char));
statemap
= (char *)calloc(imax
+1, sizeof(char));
lncntp
= (short *)calloc(imax
+1, sizeof(short));
printf("BAD SUPER BLOCK: %s\n", s
);
pwarn("USE -b OPTION TO FSCK TO SPECIFY LOCATION OF AN ALTERNATE\n");
pfatal("SUPER-BLOCK TO SUPPLY NEEDED INFORMATION; SEE fsck(8).\n");
if (inum
< ROOTINO
|| inum
> imax
)
if (inum
< startinum
|| inum
>= startinum
+ INOPB(&sblock
)) {
iblk
= itod(&sblock
, inum
);
if (getblk(&inoblk
, iblk
, sblock
.fs_bsize
) == NULL
) {
startinum
= (inum
/ INOPB(&sblock
)) * INOPB(&sblock
);
return (&inoblk
.b_un
.b_dinode
[inum
% INOPB(&sblock
)]);
switch (dp
->di_mode
& IFMT
) {
pfatal("INTERNAL ERROR: GOT TO reply()");
if (nflag
|| dfile
.wfdes
< 0) {
if (getline(stdin
, line
, sizeof(line
)) == EOF
)
if (line
[0] == 'y' || line
[0] == 'Y')
register char *p
, *lastloc
;
while ((n
= getc(fp
)) != '\n') {
if (!isspace(n
) && p
< lastloc
)
register struct filecntl
*fcp
;
dblk
= fsbtodb(&sblock
, blk
);
if (bread(fcp
, bp
->b_un
.b_buf
, dblk
, size
) != 0) {
bwrite(fcp
, bp
->b_un
.b_buf
, bp
->b_bno
, bp
->b_size
);
pfatal("CANNOT %s: BLK %ld", s
, blk
);
if (reply("CONTINUE") == 0)
errexit("Program terminated\n");
if (sblk
.b_bno
!= SBLOCK
) {
if ((dp
= ginode()) == NULL
)
if (getpw((int)dp
->di_uid
, uidbuf
) == 0) {
for (p
= uidbuf
; *p
!= ':'; p
++);
printf("%d ", dp
->di_uid
);
printf("MODE=%o\n", dp
->di_mode
);
printf("SIZE=%ld ", dp
->di_size
);
p
= ctime(&dp
->di_mtime
);
printf("MTIME=%12.12s %4.4s ", p
+4, p
+20);
daddr_t dbase
, d
, dmin
, dmax
;
register struct csum
*cs
;
sblock
.fs_cstotal
.cs_nbfree
= 0;
sblock
.fs_cstotal
.cs_nffree
= 0;
sblock
.fs_cstotal
.cs_nifree
= 0;
sblock
.fs_cstotal
.cs_ndir
= 0;
for (i
= 0; i
< howmany(sblock
.fs_cssize
, sblock
.fs_bsize
); i
++) {
sblock
.fs_csp
[i
] = (struct csum
*)calloc(1, sblock
.fs_bsize
);
getblk((char *)sblock
.fs_csp
[i
],
sblock
.fs_csaddr
+ (i
* sblock
.fs_frag
), sblock
.fs_bsize
);
for (c
= 0; c
< sblock
.fs_ncg
; c
++) {
dbase
= cgbase(&sblock
, c
);
dmax
= dbase
+ sblock
.fs_fpg
;
if (dmax
> sblock
.fs_size
)
for ( ; dmax
> sblock
.fs_size
; dmax
--)
clrbit(cgrp
.cg_free
, dmax
- dbase
);
cs
= &sblock
.fs_cs(&sblock
, c
);
cgrp
.cg_magic
= CG_MAGIC
;
cgrp
.cg_ncyl
= sblock
.fs_cpg
;
cgrp
.cg_niblk
= sblock
.fs_ipg
;
cgrp
.cg_ndblk
= dmax
- dbase
;
cgrp
.cg_cs
.cs_nffree
= 0;
cgrp
.cg_cs
.cs_nbfree
= 0;
cgrp
.cg_cs
.cs_nifree
= 0;
for (i
= 0; i
< sblock
.fs_frag
; i
++)
inum
= sblock
.fs_ipg
* c
;
for (i
= 0; i
< sblock
.fs_ipg
; inum
++, i
++) {
setbit(cgrp
.cg_iused
, i
);
clrbit(cgrp
.cg_iused
, i
);
clrbit(cgrp
.cg_iused
, i
);
for (s
= 0; s
< MAXCPG
; s
++) {
for (i
= 0; i
< NRPOS
; i
++)
dmin
+= howmany(sblock
.fs_cssize
, sblock
.fs_bsize
) * sblock
.fs_frag
;
for (d
= 0; d
< dmin
; d
++)
for (; (d
+ sblock
.fs_frag
) <= dmax
- dbase
; d
+= sblock
.fs_frag
) {
for (i
= 0; i
< sblock
.fs_frag
; i
++) {
if (!getbmap(dbase
+d
+i
)) {
setbit(cgrp
.cg_free
, d
+i
);
clrbit(cgrp
.cg_free
, d
+i
);
if (j
== sblock
.fs_frag
) {
cgrp
.cg_btot
[cbtocylno(&sblock
, d
)]++;
cgrp
.cg_b
[cbtocylno(&sblock
, d
)]
[cbtorpos(&sblock
, d
)]++;
cgrp
.cg_cs
.cs_nffree
+= j
;
blk
= ((cgrp
.cg_free
[d
/ NBBY
] >> (d
% NBBY
)) &
(0xff >> (NBBY
- sblock
.fs_frag
)));
fragacct(&sblock
, blk
, cgrp
.cg_frsum
, 1);
for (j
= d
; d
< dmax
- dbase
; d
++) {
blk
= ((cgrp
.cg_free
[j
/ NBBY
] >> (j
% NBBY
)) &
(0xff >> (NBBY
- sblock
.fs_frag
)));
fragacct(&sblock
, blk
, cgrp
.cg_frsum
, 1);
for (; d
< MAXBPG(&sblock
); d
++)
sblock
.fs_cstotal
.cs_nffree
+= cgrp
.cg_cs
.cs_nffree
;
sblock
.fs_cstotal
.cs_nbfree
+= cgrp
.cg_cs
.cs_nbfree
;
sblock
.fs_cstotal
.cs_nifree
+= cgrp
.cg_cs
.cs_nifree
;
sblock
.fs_cstotal
.cs_ndir
+= cgrp
.cg_cs
.cs_ndir
;
bwrite(&dfile
, &cgrp
, fsbtodb(&sblock
, cgtod(&sblock
, c
)),
roundup(sblock
.fs_cgsize
, DEV_BSIZE
));
for (i
= 0; i
< howmany(sblock
.fs_cssize
, sblock
.fs_bsize
); i
++) {
bwrite(&dfile
, (char *)sblock
.fs_csp
[i
],
fsbtodb(&sblock
, sblock
.fs_csaddr
+ (i
* sblock
.fs_frag
)),
* update the frsum fields to reflect addition or deletion
fragacct(fs
, fragmap
, fraglist
, cnt
)
register int field
, subfield
;
inblk
= (int)(fragtbl
[fs
->fs_frag
][fragmap
] << 1);
for (siz
= 1; siz
< fs
->fs_frag
; siz
++) {
if (((1 << siz
) & inblk
) == 0)
for (pos
= siz
; pos
<= fs
->fs_frag
; pos
++) {
if ((fragmap
& field
) == subfield
) {
for (p1
= dirp
->d_name
, p2
= srchname
;*p2
++ == *p1
; p1
++) {
if (*p1
== 0 || p1
== &dirp
->d_name
[DIRSIZ
-1]) {
if (dirp
->d_ino
>= ROOTINO
&& dirp
->d_ino
<= imax
)
while (p
> dirp
->d_name
) {
if (dirp
->d_name
[0] == '.' && dirp
->d_name
[1] == '.' &&
if ((dp
= ginode()) == NULL
)
pwarn("UNREF %s ", lostdir
? "DIR" : "FILE");
if (preen
&& dp
->di_size
== 0)
printf(" (RECONNECTED)\n");
if (reply("RECONNECT") == 0)
if ((dp
= ginode()) == NULL
) {
if ((lfdir
= parentdir
) == 0) {
pfatal("SORRY. NO lost+found DIRECTORY");
if ((dp
= ginode()) == NULL
|| !DIR || getstate() != FSTATE
) {
pfatal("SORRY. NO lost+found DIRECTORY");
if (dp
->di_size
% sblock
.fs_bsize
) {
dp
->di_size
= roundup(dp
->di_size
, sblock
.fs_bsize
);
if ((ckinode(dp
, DATA
) & ALTERD
) == 0) {
pfatal("SORRY. NO SPACE IN lost+found DIRECTORY");
if ((dp
= ginode()) != NULL
) {
pwarn("DIR I=%u CONNECTED. ", orphan
);
printf("PARENT WAS I=%u\n", pdir
);
bread(fcp
, buf
, blk
, size
)
register struct filecntl
*fcp
;
if (lseek(fcp
->rfdes
, blk
* DEV_BSIZE
, 0) < 0)
else if (read(fcp
->rfdes
, buf
, size
) == size
)
bwrite(fcp
, buf
, blk
, size
)
register struct filecntl
*fcp
;
if (lseek(fcp
->wfdes
, blk
* DEV_BSIZE
, 0) < 0)
else if (write(fcp
->wfdes
, buf
, size
) == size
) {
mask
= 0x0f << ((h
& 0x1) << 2);
return ((cp
[h
>> 1] & mask
) == mask
);
mask
= 0x03 << ((h
& 0x3) << 1);
return ((cp
[h
>> 2] & mask
) == mask
);
mask
= 0x01 << (h
& 0x7);
return ((cp
[h
>> 3] & mask
) == mask
);
error("isblock bad fs_frag %d\n", fs
->fs_frag
);