xref: /csrg-svn/sbin/fsck/utilities.c (revision 69553)
122055Sdist /*
261492Sbostic  * Copyright (c) 1980, 1986, 1993
361492Sbostic  *	The Regents of the University of California.  All rights reserved.
439976Smckusick  *
542702Sbostic  * %sccs.include.redist.c%
622055Sdist  */
722055Sdist 
816269Smckusick #ifndef lint
9*69553Smckusick static char sccsid[] = "@(#)utilities.c	8.6 (Berkeley) 05/19/95";
1039976Smckusick #endif /* not lint */
1116269Smckusick 
1216269Smckusick #include <sys/param.h>
1353703Smckusick #include <sys/time.h>
1468908Smckusick 
1551532Sbostic #include <ufs/ufs/dinode.h>
1651532Sbostic #include <ufs/ufs/dir.h>
1751532Sbostic #include <ufs/ffs/fs.h>
1868908Smckusick 
1968908Smckusick #include <ctype.h>
2068908Smckusick #include <err.h>
2144934Smckusick #include <string.h>
2268908Smckusick 
2316269Smckusick #include "fsck.h"
2416269Smckusick 
2534225Smckusick long	diskreads, totalreads;	/* Disk cache statistics */
2616269Smckusick 
2768908Smckusick static void rwerror __P((char *mesg, ufs_daddr_t blk));
2868908Smckusick 
2968908Smckusick int
ftypeok(dp)3016269Smckusick ftypeok(dp)
3139973Smckusick 	struct dinode *dp;
3216269Smckusick {
3316269Smckusick 	switch (dp->di_mode & IFMT) {
3416269Smckusick 
3516269Smckusick 	case IFDIR:
3616269Smckusick 	case IFREG:
3716269Smckusick 	case IFBLK:
3816269Smckusick 	case IFCHR:
3916269Smckusick 	case IFLNK:
4016269Smckusick 	case IFSOCK:
4142943Smckusick 	case IFIFO:
4216269Smckusick 		return (1);
4316269Smckusick 
4416269Smckusick 	default:
4516269Smckusick 		if (debug)
4616269Smckusick 			printf("bad file type 0%o\n", dp->di_mode);
4716269Smckusick 		return (0);
4816269Smckusick 	}
4916269Smckusick }
5016269Smckusick 
5168908Smckusick int
reply(question)5239975Smckusick reply(question)
5339975Smckusick 	char *question;
5416269Smckusick {
5539975Smckusick 	int persevere;
5639975Smckusick 	char c;
5716269Smckusick 
5816269Smckusick 	if (preen)
5916269Smckusick 		pfatal("INTERNAL ERROR: GOT TO reply()");
6039975Smckusick 	persevere = !strcmp(question, "CONTINUE");
6139975Smckusick 	printf("\n");
6239975Smckusick 	if (!persevere && (nflag || fswritefd < 0)) {
6339975Smckusick 		printf("%s? no\n\n", question);
6416269Smckusick 		return (0);
6516269Smckusick 	}
6639975Smckusick 	if (yflag || (persevere && nflag)) {
6739975Smckusick 		printf("%s? yes\n\n", question);
6816269Smckusick 		return (1);
6916269Smckusick 	}
7039975Smckusick 	do	{
7139975Smckusick 		printf("%s? [yn] ", question);
7239975Smckusick 		(void) fflush(stdout);
7339975Smckusick 		c = getc(stdin);
7439975Smckusick 		while (c != '\n' && getc(stdin) != '\n')
7539975Smckusick 			if (feof(stdin))
7639975Smckusick 				return (0);
7739975Smckusick 	} while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
7816269Smckusick 	printf("\n");
7939975Smckusick 	if (c == 'y' || c == 'Y')
8016269Smckusick 		return (1);
8139975Smckusick 	return (0);
8216269Smckusick }
8316269Smckusick 
8434225Smckusick /*
8534225Smckusick  * Malloc buffers and set up cache.
8634225Smckusick  */
8768908Smckusick void
bufinit()8834225Smckusick bufinit()
8934225Smckusick {
9039973Smckusick 	register struct bufarea *bp;
9134225Smckusick 	long bufcnt, i;
9234225Smckusick 	char *bufp;
9334225Smckusick 
9440649Smckusick 	pbp = pdirbp = (struct bufarea *)0;
9539973Smckusick 	bufp = malloc((unsigned int)sblock.fs_bsize);
9634225Smckusick 	if (bufp == 0)
9768908Smckusick 		errx(EEXIT, "cannot allocate buffer pool");
9834225Smckusick 	cgblk.b_un.b_buf = bufp;
9934225Smckusick 	initbarea(&cgblk);
10034225Smckusick 	bufhead.b_next = bufhead.b_prev = &bufhead;
10134225Smckusick 	bufcnt = MAXBUFSPACE / sblock.fs_bsize;
10234225Smckusick 	if (bufcnt < MINBUFS)
10334225Smckusick 		bufcnt = MINBUFS;
10434225Smckusick 	for (i = 0; i < bufcnt; i++) {
10539973Smckusick 		bp = (struct bufarea *)malloc(sizeof(struct bufarea));
10639973Smckusick 		bufp = malloc((unsigned int)sblock.fs_bsize);
10738377Smckusick 		if (bp == NULL || bufp == NULL) {
10834225Smckusick 			if (i >= MINBUFS)
10934225Smckusick 				break;
11068908Smckusick 			errx(EEXIT, "cannot allocate buffer pool");
11134225Smckusick 		}
11234225Smckusick 		bp->b_un.b_buf = bufp;
11334225Smckusick 		bp->b_prev = &bufhead;
11434225Smckusick 		bp->b_next = bufhead.b_next;
11534225Smckusick 		bufhead.b_next->b_prev = bp;
11634225Smckusick 		bufhead.b_next = bp;
11734225Smckusick 		initbarea(bp);
11834225Smckusick 	}
11934482Smckusick 	bufhead.b_size = i;	/* save number of buffers */
12034225Smckusick }
12134225Smckusick 
12234225Smckusick /*
12334225Smckusick  * Manage a cache of directory blocks.
12434225Smckusick  */
12539973Smckusick struct bufarea *
getdatablk(blkno,size)12634225Smckusick getdatablk(blkno, size)
12768548Smckusick 	ufs_daddr_t blkno;
12834225Smckusick 	long size;
12934225Smckusick {
13039973Smckusick 	register struct bufarea *bp;
13134225Smckusick 
13234225Smckusick 	for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next)
13334671Smckusick 		if (bp->b_bno == fsbtodb(&sblock, blkno))
13434225Smckusick 			goto foundit;
13534225Smckusick 	for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev)
13634225Smckusick 		if ((bp->b_flags & B_INUSE) == 0)
13734225Smckusick 			break;
13834225Smckusick 	if (bp == &bufhead)
13968908Smckusick 		errx(EEXIT, "deadlocked buffer pool");
14034225Smckusick 	getblk(bp, blkno, size);
14134225Smckusick 	/* fall through */
14234225Smckusick foundit:
14334225Smckusick 	totalreads++;
14434225Smckusick 	bp->b_prev->b_next = bp->b_next;
14534225Smckusick 	bp->b_next->b_prev = bp->b_prev;
14634225Smckusick 	bp->b_prev = &bufhead;
14734225Smckusick 	bp->b_next = bufhead.b_next;
14834225Smckusick 	bufhead.b_next->b_prev = bp;
14934225Smckusick 	bufhead.b_next = bp;
15034225Smckusick 	bp->b_flags |= B_INUSE;
15134225Smckusick 	return (bp);
15234225Smckusick }
15334225Smckusick 
15444934Smckusick void
getblk(bp,blk,size)15516269Smckusick getblk(bp, blk, size)
15639973Smckusick 	register struct bufarea *bp;
15768548Smckusick 	ufs_daddr_t blk;
15816269Smckusick 	long size;
15916269Smckusick {
16068548Smckusick 	ufs_daddr_t dblk;
16116269Smckusick 
16234671Smckusick 	dblk = fsbtodb(&sblock, blk);
16344934Smckusick 	if (bp->b_bno != dblk) {
16444934Smckusick 		flush(fswritefd, bp);
16544934Smckusick 		diskreads++;
16644934Smckusick 		bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, dblk, size);
16744934Smckusick 		bp->b_bno = dblk;
16844934Smckusick 		bp->b_size = size;
16944934Smckusick 	}
17016269Smckusick }
17116269Smckusick 
17268908Smckusick void
flush(fd,bp)17339973Smckusick flush(fd, bp)
17439973Smckusick 	int fd;
17539973Smckusick 	register struct bufarea *bp;
17616269Smckusick {
17717931Smckusick 	register int i, j;
17816269Smckusick 
17917931Smckusick 	if (!bp->b_dirty)
18017931Smckusick 		return;
18121540Smckusick 	if (bp->b_errs != 0)
18230609Skarels 		pfatal("WRITING %sZERO'ED BLOCK %d TO DISK\n",
18330609Skarels 		    (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ",
18430609Skarels 		    bp->b_bno);
18516269Smckusick 	bp->b_dirty = 0;
18621540Smckusick 	bp->b_errs = 0;
18739973Smckusick 	bwrite(fd, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size);
18817931Smckusick 	if (bp != &sblk)
18917931Smckusick 		return;
19017931Smckusick 	for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
19139973Smckusick 		bwrite(fswritefd, (char *)sblock.fs_csp[j],
19217931Smckusick 		    fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
19317931Smckusick 		    sblock.fs_cssize - i < sblock.fs_bsize ?
19417931Smckusick 		    sblock.fs_cssize - i : sblock.fs_bsize);
19517931Smckusick 	}
19616269Smckusick }
19716269Smckusick 
19868908Smckusick static void
rwerror(mesg,blk)19939973Smckusick rwerror(mesg, blk)
20039973Smckusick 	char *mesg;
20168548Smckusick 	ufs_daddr_t blk;
20216269Smckusick {
20316269Smckusick 
20416269Smckusick 	if (preen == 0)
20516269Smckusick 		printf("\n");
20639973Smckusick 	pfatal("CANNOT %s: BLK %ld", mesg, blk);
20716269Smckusick 	if (reply("CONTINUE") == 0)
20868908Smckusick 		exit(EEXIT);
20916269Smckusick }
21016269Smckusick 
21168908Smckusick void
ckfini(markclean)21269319Smckusick ckfini(markclean)
21369319Smckusick 	int markclean;
21416269Smckusick {
21539973Smckusick 	register struct bufarea *bp, *nbp;
216*69553Smckusick 	int ofsmodified, cnt = 0;
21716269Smckusick 
21856809Smckusick 	if (fswritefd < 0) {
21956809Smckusick 		(void)close(fsreadfd);
22056809Smckusick 		return;
22156809Smckusick 	}
22239973Smckusick 	flush(fswritefd, &sblk);
22330859Skarels 	if (havesb && sblk.b_bno != SBOFF / dev_bsize &&
22430518Smckusick 	    !preen && reply("UPDATE STANDARD SUPERBLOCK")) {
22530556Smckusick 		sblk.b_bno = SBOFF / dev_bsize;
22616269Smckusick 		sbdirty();
22739973Smckusick 		flush(fswritefd, &sblk);
22816269Smckusick 	}
22939973Smckusick 	flush(fswritefd, &cgblk);
23038342Smckusick 	free(cgblk.b_un.b_buf);
23156809Smckusick 	for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) {
23234482Smckusick 		cnt++;
23339973Smckusick 		flush(fswritefd, bp);
23438342Smckusick 		nbp = bp->b_prev;
23538342Smckusick 		free(bp->b_un.b_buf);
23638342Smckusick 		free((char *)bp);
23734482Smckusick 	}
23834482Smckusick 	if (bufhead.b_size != cnt)
23968908Smckusick 		errx(EEXIT, "Panic: lost %d buffers", bufhead.b_size - cnt);
24040649Smckusick 	pbp = pdirbp = (struct bufarea *)0;
24169319Smckusick 	if (markclean && sblock.fs_clean == 0) {
24269319Smckusick 		sblock.fs_clean = 1;
24369319Smckusick 		sbdirty();
244*69553Smckusick 		ofsmodified = fsmodified;
24569319Smckusick 		flush(fswritefd, &sblk);
246*69553Smckusick 		fsmodified = ofsmodified;
247*69553Smckusick 		if (!preen)
248*69553Smckusick 			printf("\n***** FILE SYSTEM MARKED CLEAN *****\n");
24969319Smckusick 	}
25034225Smckusick 	if (debug)
25144934Smckusick 		printf("cache missed %ld of %ld (%d%%)\n", diskreads,
25244934Smckusick 		    totalreads, (int)(diskreads * 100 / totalreads));
25339973Smckusick 	(void)close(fsreadfd);
25439973Smckusick 	(void)close(fswritefd);
25516269Smckusick }
25616269Smckusick 
25768908Smckusick int
bread(fd,buf,blk,size)25839973Smckusick bread(fd, buf, blk, size)
25939973Smckusick 	int fd;
26016269Smckusick 	char *buf;
26168548Smckusick 	ufs_daddr_t blk;
26216269Smckusick 	long size;
26316269Smckusick {
26421540Smckusick 	char *cp;
26521540Smckusick 	int i, errs;
26660638Smckusick 	off_t offset;
26721540Smckusick 
26860638Smckusick 	offset = blk;
26960638Smckusick 	offset *= dev_bsize;
27060638Smckusick 	if (lseek(fd, offset, 0) < 0)
27139973Smckusick 		rwerror("SEEK", blk);
27239973Smckusick 	else if (read(fd, buf, (int)size) == size)
27321540Smckusick 		return (0);
27439973Smckusick 	rwerror("READ", blk);
27560638Smckusick 	if (lseek(fd, offset, 0) < 0)
27639973Smckusick 		rwerror("SEEK", blk);
27721540Smckusick 	errs = 0;
27868992Sbostic 	memset(buf, 0, (size_t)size);
27930609Skarels 	printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:");
28030609Skarels 	for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) {
28144999Smckusick 		if (read(fd, cp, (int)secsize) != secsize) {
28260638Smckusick 			(void)lseek(fd, offset + i + secsize, 0);
28330859Skarels 			if (secsize != dev_bsize && dev_bsize != 1)
28444934Smckusick 				printf(" %ld (%ld),",
28530609Skarels 				    (blk * dev_bsize + i) / secsize,
28630609Skarels 				    blk + i / dev_bsize);
28730609Skarels 			else
28844934Smckusick 				printf(" %ld,", blk + i / dev_bsize);
28921540Smckusick 			errs++;
29021540Smckusick 		}
29121540Smckusick 	}
29221758Smckusick 	printf("\n");
29321540Smckusick 	return (errs);
29416269Smckusick }
29516269Smckusick 
29668908Smckusick void
bwrite(fd,buf,blk,size)29739973Smckusick bwrite(fd, buf, blk, size)
29839973Smckusick 	int fd;
29916269Smckusick 	char *buf;
30068548Smckusick 	ufs_daddr_t blk;
30116269Smckusick 	long size;
30216269Smckusick {
30321758Smckusick 	int i;
30421758Smckusick 	char *cp;
30560638Smckusick 	off_t offset;
30616269Smckusick 
30739973Smckusick 	if (fd < 0)
30821758Smckusick 		return;
30960638Smckusick 	offset = blk;
31060638Smckusick 	offset *= dev_bsize;
31160638Smckusick 	if (lseek(fd, offset, 0) < 0)
31239973Smckusick 		rwerror("SEEK", blk);
31339973Smckusick 	else if (write(fd, buf, (int)size) == size) {
31439973Smckusick 		fsmodified = 1;
31521758Smckusick 		return;
31616269Smckusick 	}
31739973Smckusick 	rwerror("WRITE", blk);
31860638Smckusick 	if (lseek(fd, offset, 0) < 0)
31939973Smckusick 		rwerror("SEEK", blk);
32030609Skarels 	printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:");
32130518Smckusick 	for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize)
32244999Smckusick 		if (write(fd, cp, (int)dev_bsize) != dev_bsize) {
32360638Smckusick 			(void)lseek(fd, offset + i + dev_bsize, 0);
32444934Smckusick 			printf(" %ld,", blk + i / dev_bsize);
32530395Smckusick 		}
32621758Smckusick 	printf("\n");
32721758Smckusick 	return;
32816269Smckusick }
32916269Smckusick 
33017944Smckusick /*
33117944Smckusick  * allocate a data block with the specified number of fragments
33217944Smckusick  */
33368908Smckusick ufs_daddr_t
allocblk(frags)33417944Smckusick allocblk(frags)
33539973Smckusick 	long frags;
33617944Smckusick {
33717944Smckusick 	register int i, j, k;
33817944Smckusick 
33917944Smckusick 	if (frags <= 0 || frags > sblock.fs_frag)
34017944Smckusick 		return (0);
34139973Smckusick 	for (i = 0; i < maxfsblock - sblock.fs_frag; i += sblock.fs_frag) {
34217944Smckusick 		for (j = 0; j <= sblock.fs_frag - frags; j++) {
34339973Smckusick 			if (testbmap(i + j))
34417944Smckusick 				continue;
34517944Smckusick 			for (k = 1; k < frags; k++)
34639973Smckusick 				if (testbmap(i + j + k))
34717944Smckusick 					break;
34817944Smckusick 			if (k < frags) {
34917944Smckusick 				j += k;
35017944Smckusick 				continue;
35117944Smckusick 			}
35217944Smckusick 			for (k = 0; k < frags; k++)
35317944Smckusick 				setbmap(i + j + k);
35417944Smckusick 			n_blks += frags;
35517944Smckusick 			return (i + j);
35617944Smckusick 		}
35717944Smckusick 	}
35817944Smckusick 	return (0);
35917944Smckusick }
36017944Smckusick 
36117944Smckusick /*
36217944Smckusick  * Free a previously allocated block
36317944Smckusick  */
36468908Smckusick void
freeblk(blkno,frags)36517944Smckusick freeblk(blkno, frags)
36668548Smckusick 	ufs_daddr_t blkno;
36739973Smckusick 	long frags;
36817944Smckusick {
36917944Smckusick 	struct inodesc idesc;
37017944Smckusick 
37117944Smckusick 	idesc.id_blkno = blkno;
37217944Smckusick 	idesc.id_numfrags = frags;
37344934Smckusick 	(void)pass4check(&idesc);
37417944Smckusick }
37517944Smckusick 
37617991Smckusick /*
37717991Smckusick  * Find a pathname
37817991Smckusick  */
37968908Smckusick void
getpathname(namebuf,curdir,ino)38017991Smckusick getpathname(namebuf, curdir, ino)
38117991Smckusick 	char *namebuf;
38217991Smckusick 	ino_t curdir, ino;
38317991Smckusick {
38417991Smckusick 	int len;
38517991Smckusick 	register char *cp;
38617991Smckusick 	struct inodesc idesc;
38744999Smckusick 	static int busy = 0;
38817991Smckusick 	extern int findname();
38917991Smckusick 
39054600Smckusick 	if (curdir == ino && ino == ROOTINO) {
39154600Smckusick 		(void)strcpy(namebuf, "/");
39254600Smckusick 		return;
39354600Smckusick 	}
39444999Smckusick 	if (busy ||
39544999Smckusick 	    (statemap[curdir] != DSTATE && statemap[curdir] != DFOUND)) {
39644934Smckusick 		(void)strcpy(namebuf, "?");
39717991Smckusick 		return;
39817991Smckusick 	}
39944999Smckusick 	busy = 1;
40068992Sbostic 	memset(&idesc, 0, sizeof(struct inodesc));
40117991Smckusick 	idesc.id_type = DATA;
40244999Smckusick 	idesc.id_fix = IGNORE;
40340646Smckusick 	cp = &namebuf[MAXPATHLEN - 1];
40430354Smckusick 	*cp = '\0';
40517991Smckusick 	if (curdir != ino) {
40617991Smckusick 		idesc.id_parent = curdir;
40717991Smckusick 		goto namelookup;
40817991Smckusick 	}
40917991Smckusick 	while (ino != ROOTINO) {
41017991Smckusick 		idesc.id_number = ino;
41117991Smckusick 		idesc.id_func = findino;
41217991Smckusick 		idesc.id_name = "..";
41340019Smckusick 		if ((ckinode(ginode(ino), &idesc) & FOUND) == 0)
41417991Smckusick 			break;
41517991Smckusick 	namelookup:
41617991Smckusick 		idesc.id_number = idesc.id_parent;
41717991Smckusick 		idesc.id_parent = ino;
41817991Smckusick 		idesc.id_func = findname;
41917991Smckusick 		idesc.id_name = namebuf;
42040019Smckusick 		if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0)
42117991Smckusick 			break;
42217991Smckusick 		len = strlen(namebuf);
42317991Smckusick 		cp -= len;
42468992Sbostic 		memmove(cp, namebuf, (size_t)len);
42550572Smckusick 		*--cp = '/';
42617991Smckusick 		if (cp < &namebuf[MAXNAMLEN])
42717991Smckusick 			break;
42817991Smckusick 		ino = idesc.id_number;
42917991Smckusick 	}
43044999Smckusick 	busy = 0;
43150572Smckusick 	if (ino != ROOTINO)
43250572Smckusick 		*--cp = '?';
43368992Sbostic 	memmove(namebuf, cp, (size_t)(&namebuf[MAXPATHLEN] - cp));
43417991Smckusick }
43517991Smckusick 
43639165Sbostic void
catch(sig)43768908Smckusick catch(sig)
43868908Smckusick 	int sig;
43916269Smckusick {
44054600Smckusick 	if (!doinglevel2)
44169319Smckusick 		ckfini(0);
44216269Smckusick 	exit(12);
44316269Smckusick }
44416269Smckusick 
44516269Smckusick /*
44624680Skarels  * When preening, allow a single quit to signal
44724680Skarels  * a special exit after filesystem checks complete
44824680Skarels  * so that reboot sequence may be interrupted.
44924680Skarels  */
45039165Sbostic void
catchquit(sig)45168908Smckusick catchquit(sig)
45268908Smckusick 	int sig;
45324680Skarels {
45424680Skarels 	extern returntosingle;
45524680Skarels 
45624680Skarels 	printf("returning to single-user after filesystem check\n");
45724680Skarels 	returntosingle = 1;
45824680Skarels 	(void)signal(SIGQUIT, SIG_DFL);
45924680Skarels }
46024680Skarels 
46124680Skarels /*
46224680Skarels  * Ignore a single quit signal; wait and flush just in case.
46324680Skarels  * Used by child processes in preen.
46424680Skarels  */
46539165Sbostic void
voidquit(sig)46668908Smckusick voidquit(sig)
46768908Smckusick 	int sig;
46824680Skarels {
46924680Skarels 
47024680Skarels 	sleep(1);
47124680Skarels 	(void)signal(SIGQUIT, SIG_IGN);
47224680Skarels 	(void)signal(SIGQUIT, SIG_DFL);
47324680Skarels }
47424680Skarels 
47524680Skarels /*
47616269Smckusick  * determine whether an inode should be fixed.
47716269Smckusick  */
47868908Smckusick int
dofix(idesc,msg)47917931Smckusick dofix(idesc, msg)
48016269Smckusick 	register struct inodesc *idesc;
48117931Smckusick 	char *msg;
48216269Smckusick {
48316269Smckusick 
48416269Smckusick 	switch (idesc->id_fix) {
48516269Smckusick 
48616269Smckusick 	case DONTKNOW:
48717931Smckusick 		if (idesc->id_type == DATA)
48839973Smckusick 			direrror(idesc->id_number, msg);
48917931Smckusick 		else
49017931Smckusick 			pwarn(msg);
49117931Smckusick 		if (preen) {
49217931Smckusick 			printf(" (SALVAGED)\n");
49317931Smckusick 			idesc->id_fix = FIX;
49417931Smckusick 			return (ALTERED);
49517931Smckusick 		}
49616269Smckusick 		if (reply("SALVAGE") == 0) {
49716269Smckusick 			idesc->id_fix = NOFIX;
49816269Smckusick 			return (0);
49916269Smckusick 		}
50016269Smckusick 		idesc->id_fix = FIX;
50116269Smckusick 		return (ALTERED);
50216269Smckusick 
50316269Smckusick 	case FIX:
50416269Smckusick 		return (ALTERED);
50516269Smckusick 
50616269Smckusick 	case NOFIX:
50744999Smckusick 	case IGNORE:
50816269Smckusick 		return (0);
50916269Smckusick 
51016269Smckusick 	default:
51168908Smckusick 		errx(EEXIT, "UNKNOWN INODESC FIX MODE %d", idesc->id_fix);
51216269Smckusick 	}
51316269Smckusick 	/* NOTREACHED */
51468908Smckusick 	return (0);
51516269Smckusick }
51616269Smckusick 
51768908Smckusick #if __STDC__
51868908Smckusick #include <stdarg.h>
51968908Smckusick #else
52068908Smckusick #include <varargs.h>
52168908Smckusick #endif
52216269Smckusick 
52316269Smckusick /*
52439973Smckusick  * An unexpected inconsistency occured.
52539973Smckusick  * Die if preening, otherwise just print message and continue.
52616269Smckusick  */
52768908Smckusick void
52868908Smckusick #if __STDC__
pfatal(const char * fmt,...)52968908Smckusick pfatal(const char *fmt, ...)
53068908Smckusick #else
53168908Smckusick pfatal(fmt, va_alist)
53268908Smckusick 	char *fmt;
53368908Smckusick 	va_dcl
53468908Smckusick #endif
53516269Smckusick {
53668908Smckusick 	va_list ap;
53768908Smckusick #if __STDC__
53868908Smckusick 	va_start(ap, fmt);
53968908Smckusick #else
54068908Smckusick 	va_start(ap);
54168908Smckusick #endif
54268908Smckusick 	if (!preen) {
54368908Smckusick 		(void)vfprintf(stderr, fmt, ap);
54468908Smckusick 		va_end(ap);
54568908Smckusick 		return;
54616269Smckusick 	}
54768908Smckusick 	(void)fprintf(stderr, "%s: ", cdevname);
54868908Smckusick 	(void)vfprintf(stderr, fmt, ap);
54968908Smckusick 	(void)fprintf(stderr,
55068908Smckusick 	    "\n%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
55168908Smckusick 	    cdevname);
55268908Smckusick 	exit(EEXIT);
55316269Smckusick }
55416269Smckusick 
55516269Smckusick /*
55639973Smckusick  * Pwarn just prints a message when not preening,
55716269Smckusick  * or a warning (preceded by filename) when preening.
55816269Smckusick  */
55968908Smckusick void
56068908Smckusick #if __STDC__
pwarn(const char * fmt,...)56168908Smckusick pwarn(const char *fmt, ...)
56268908Smckusick #else
56368908Smckusick pwarn(fmt, va_alist)
56468908Smckusick 	char *fmt;
56568908Smckusick 	va_dcl
56668908Smckusick #endif
56716269Smckusick {
56868908Smckusick 	va_list ap;
56968908Smckusick #if __STDC__
57068908Smckusick 	va_start(ap, fmt);
57168908Smckusick #else
57268908Smckusick 	va_start(ap);
57368908Smckusick #endif
57416269Smckusick 	if (preen)
57568908Smckusick 		(void)fprintf(stderr, "%s: ", cdevname);
57668908Smckusick 	(void)vfprintf(stderr, fmt, ap);
57768908Smckusick 	va_end(ap);
57816269Smckusick }
57916269Smckusick 
58016269Smckusick /*
58116269Smckusick  * Stub for routines from kernel.
58216269Smckusick  */
58368908Smckusick void
58468908Smckusick #if __STDC__
panic(const char * fmt,...)58568908Smckusick panic(const char *fmt, ...)
58668908Smckusick #else
58768908Smckusick panic(fmt, va_alist)
58868908Smckusick 	char *fmt;
58968908Smckusick 	va_dcl
59068908Smckusick #endif
59116269Smckusick {
59268908Smckusick 	va_list ap;
59368908Smckusick #if __STDC__
59468908Smckusick 	va_start(ap, fmt);
59568908Smckusick #else
59668908Smckusick 	va_start(ap);
59768908Smckusick #endif
59817931Smckusick 	pfatal("INTERNAL INCONSISTENCY:");
59968908Smckusick 	(void)vfprintf(stderr, fmt, ap);
60068908Smckusick 	va_end(ap);
60168908Smckusick 	exit(EEXIT);
60216269Smckusick }
603