* Copyright (c) 1980, 1986 The Regents of the University of California.
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)utilities.c 5.30 (Berkeley) %G%";
long diskreads
, totalreads
; /* Disk cache statistics */
switch (dp
->di_mode
& IFMT
) {
printf("bad file type 0%o\n", dp
->di_mode
);
pfatal("INTERNAL ERROR: GOT TO reply()");
persevere
= !strcmp(question
, "CONTINUE");
if (!persevere
&& (nflag
|| fswritefd
< 0)) {
printf("%s? no\n\n", question
);
if (yflag
|| (persevere
&& nflag
)) {
printf("%s? yes\n\n", question
);
printf("%s? [yn] ", question
);
while (c
!= '\n' && getc(stdin
) != '\n')
} while (c
!= 'y' && c
!= 'Y' && c
!= 'n' && c
!= 'N');
if (c
== 'y' || c
== 'Y')
* Malloc buffers and set up cache.
register struct bufarea
*bp
;
pbp
= pdirbp
= (struct bufarea
*)0;
bufp
= malloc((unsigned int)sblock
.fs_bsize
);
errexit("cannot allocate buffer pool\n");
bufhead
.b_next
= bufhead
.b_prev
= &bufhead
;
bufcnt
= MAXBUFSPACE
/ sblock
.fs_bsize
;
for (i
= 0; i
< bufcnt
; i
++) {
bp
= (struct bufarea
*)malloc(sizeof(struct bufarea
));
bufp
= malloc((unsigned int)sblock
.fs_bsize
);
if (bp
== NULL
|| bufp
== NULL
) {
errexit("cannot allocate buffer pool\n");
bp
->b_next
= bufhead
.b_next
;
bufhead
.b_next
->b_prev
= bp
;
bufhead
.b_size
= i
; /* save number of buffers */
* Manage a cache of directory blocks.
register struct bufarea
*bp
;
for (bp
= bufhead
.b_next
; bp
!= &bufhead
; bp
= bp
->b_next
)
if (bp
->b_bno
== fsbtodb(&sblock
, blkno
))
for (bp
= bufhead
.b_prev
; bp
!= &bufhead
; bp
= bp
->b_prev
)
if ((bp
->b_flags
& B_INUSE
) == 0)
errexit("deadlocked buffer pool\n");
bp
->b_prev
->b_next
= bp
->b_next
;
bp
->b_next
->b_prev
= bp
->b_prev
;
bp
->b_next
= bufhead
.b_next
;
bufhead
.b_next
->b_prev
= bp
;
register struct bufarea
*bp
;
dblk
= fsbtodb(&sblock
, blk
);
bp
->b_errs
= bread(fsreadfd
, bp
->b_un
.b_buf
, dblk
, size
);
register struct bufarea
*bp
;
pfatal("WRITING %sZERO'ED BLOCK %d TO DISK\n",
(bp
->b_errs
== bp
->b_size
/ dev_bsize
) ? "" : "PARTIALLY ",
bwrite(fd
, bp
->b_un
.b_buf
, bp
->b_bno
, (long)bp
->b_size
);
for (i
= 0, j
= 0; i
< sblock
.fs_cssize
; i
+= sblock
.fs_bsize
, j
++) {
bwrite(fswritefd
, (char *)sblock
.fs_csp
[j
],
fsbtodb(&sblock
, sblock
.fs_csaddr
+ j
* sblock
.fs_frag
),
sblock
.fs_cssize
- i
< sblock
.fs_bsize
?
sblock
.fs_cssize
- i
: sblock
.fs_bsize
);
pfatal("CANNOT %s: BLK %ld", mesg
, blk
);
if (reply("CONTINUE") == 0)
errexit("Program terminated\n");
register struct bufarea
*bp
, *nbp
;
if (havesb
&& sblk
.b_bno
!= SBOFF
/ dev_bsize
&&
!preen
&& reply("UPDATE STANDARD SUPERBLOCK")) {
sblk
.b_bno
= SBOFF
/ dev_bsize
;
flush(fswritefd
, &cgblk
);
for (bp
= bufhead
.b_prev
; bp
!= &bufhead
; bp
= nbp
) {
if (bufhead
.b_size
!= cnt
)
errexit("Panic: lost %d buffers\n", bufhead
.b_size
- cnt
);
pbp
= pdirbp
= (struct bufarea
*)0;
printf("cache missed %ld of %ld (%d%%)\n", diskreads
,
totalreads
, (int)(diskreads
* 100 / totalreads
));
bread(fd
, buf
, blk
, size
)
if (lseek(fd
, blk
* dev_bsize
, 0) < 0)
else if (read(fd
, buf
, (int)size
) == size
)
if (lseek(fd
, blk
* dev_bsize
, 0) < 0)
bzero(buf
, (size_t)size
);
printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:");
for (cp
= buf
, i
= 0; i
< size
; i
+= secsize
, cp
+= secsize
) {
if (read(fd
, cp
, (int)secsize
) != secsize
) {
(void)lseek(fd
, blk
* dev_bsize
+ i
+ secsize
, 0);
if (secsize
!= dev_bsize
&& dev_bsize
!= 1)
(blk
* dev_bsize
+ i
) / secsize
,
printf(" %ld,", blk
+ i
/ dev_bsize
);
bwrite(fd
, buf
, blk
, size
)
if (lseek(fd
, blk
* dev_bsize
, 0) < 0)
else if (write(fd
, buf
, (int)size
) == size
) {
if (lseek(fd
, blk
* dev_bsize
, 0) < 0)
printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:");
for (cp
= buf
, i
= 0; i
< size
; i
+= dev_bsize
, cp
+= dev_bsize
)
if (write(fd
, cp
, (int)dev_bsize
) != dev_bsize
) {
(void)lseek(fd
, blk
* dev_bsize
+ i
+ dev_bsize
, 0);
printf(" %ld,", blk
+ i
/ dev_bsize
);
* allocate a data block with the specified number of fragments
if (frags
<= 0 || frags
> sblock
.fs_frag
)
for (i
= 0; i
< maxfsblock
- sblock
.fs_frag
; i
+= sblock
.fs_frag
) {
for (j
= 0; j
<= sblock
.fs_frag
- frags
; j
++) {
for (k
= 1; k
< frags
; k
++)
for (k
= 0; k
< frags
; k
++)
* Free a previously allocated block
idesc
.id_numfrags
= frags
;
(void)pass4check(&idesc
);
getpathname(namebuf
, curdir
, ino
)
(statemap
[curdir
] != DSTATE
&& statemap
[curdir
] != DFOUND
)) {
(void)strcpy(namebuf
, "?");
bzero((char *)&idesc
, sizeof(struct inodesc
));
cp
= &namebuf
[MAXPATHLEN
- 1];
idesc
.id_parent
= curdir
;
if ((ckinode(ginode(ino
), &idesc
) & FOUND
) == 0)
idesc
.id_number
= idesc
.id_parent
;
idesc
.id_func
= findname
;
if ((ckinode(ginode(idesc
.id_number
), &idesc
)&FOUND
) == 0)
bcopy(namebuf
, cp
, (size_t)len
);
if (cp
< &namebuf
[MAXNAMLEN
])
bcopy(cp
, namebuf
, (size_t)(&namebuf
[MAXPATHLEN
] - cp
));
* When preening, allow a single quit to signal
* a special exit after filesystem checks complete
* so that reboot sequence may be interrupted.
printf("returning to single-user after filesystem check\n");
(void)signal(SIGQUIT
, SIG_DFL
);
* Ignore a single quit signal; wait and flush just in case.
* Used by child processes in preen.
(void)signal(SIGQUIT
, SIG_IGN
);
(void)signal(SIGQUIT
, SIG_DFL
);
* determine whether an inode should be fixed.
register struct inodesc
*idesc
;
if (idesc
->id_type
== DATA
)
direrror(idesc
->id_number
, msg
);
if (reply("SALVAGE") == 0) {
errexit("UNKNOWN INODESC FIX MODE %d\n", idesc
->id_fix
);
* An unexpected inconsistency occured.
* Die if preening, otherwise just print message and continue.
printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
* Pwarn just prints a message when not preening,
* or a warning (preceded by filename) when preening.
pwarn(s
, a1
, a2
, a3
, a4
, a5
, a6
)
printf(s
, a1
, a2
, a3
, a4
, a5
, a6
);
* Stub for routines from kernel.
pfatal("INTERNAL INCONSISTENCY:");