xref: /csrg-svn/sbin/fsck/utilities.c (revision 34225)
122055Sdist /*
222055Sdist  * Copyright (c) 1980 Regents of the University of California.
322055Sdist  * All rights reserved.  The Berkeley software License Agreement
422055Sdist  * specifies the terms and conditions for redistribution.
522055Sdist  */
622055Sdist 
716269Smckusick #ifndef lint
8*34225Smckusick static char sccsid[] = "@(#)utilities.c	5.11 (Berkeley) 05/07/88";
922055Sdist #endif not lint
1016269Smckusick 
1116269Smckusick #include <stdio.h>
1216269Smckusick #include <ctype.h>
1316269Smckusick #include <sys/param.h>
1416269Smckusick #include <sys/inode.h>
1516269Smckusick #include <sys/fs.h>
1617991Smckusick #include <sys/dir.h>
1716269Smckusick #include "fsck.h"
1816269Smckusick 
19*34225Smckusick long	diskreads, totalreads;	/* Disk cache statistics */
2016269Smckusick long	lseek();
2116269Smckusick 
2216269Smckusick ftypeok(dp)
2316269Smckusick 	DINODE *dp;
2416269Smckusick {
2516269Smckusick 	switch (dp->di_mode & IFMT) {
2616269Smckusick 
2716269Smckusick 	case IFDIR:
2816269Smckusick 	case IFREG:
2916269Smckusick 	case IFBLK:
3016269Smckusick 	case IFCHR:
3116269Smckusick 	case IFLNK:
3216269Smckusick 	case IFSOCK:
3316269Smckusick 		return (1);
3416269Smckusick 
3516269Smckusick 	default:
3616269Smckusick 		if (debug)
3716269Smckusick 			printf("bad file type 0%o\n", dp->di_mode);
3816269Smckusick 		return (0);
3916269Smckusick 	}
4016269Smckusick }
4116269Smckusick 
4216269Smckusick reply(s)
4316269Smckusick 	char *s;
4416269Smckusick {
4516269Smckusick 	char line[80];
4630609Skarels 	int cont = (strcmp(s, "CONTINUE") == 0);
4716269Smckusick 
4816269Smckusick 	if (preen)
4916269Smckusick 		pfatal("INTERNAL ERROR: GOT TO reply()");
5016269Smckusick 	printf("\n%s? ", s);
5130609Skarels 	if (!cont && (nflag || dfile.wfdes < 0)) {
5216269Smckusick 		printf(" no\n\n");
5316269Smckusick 		return (0);
5416269Smckusick 	}
5530609Skarels 	if (yflag || (cont && nflag)) {
5616269Smckusick 		printf(" yes\n\n");
5716269Smckusick 		return (1);
5816269Smckusick 	}
5916269Smckusick 	if (getline(stdin, line, sizeof(line)) == EOF)
6016269Smckusick 		errexit("\n");
6116269Smckusick 	printf("\n");
6216269Smckusick 	if (line[0] == 'y' || line[0] == 'Y')
6316269Smckusick 		return (1);
6416269Smckusick 	else
6516269Smckusick 		return (0);
6616269Smckusick }
6716269Smckusick 
6816269Smckusick getline(fp, loc, maxlen)
6916269Smckusick 	FILE *fp;
7016269Smckusick 	char *loc;
7116269Smckusick {
7216269Smckusick 	register n;
7316269Smckusick 	register char *p, *lastloc;
7416269Smckusick 
7516269Smckusick 	p = loc;
7616269Smckusick 	lastloc = &p[maxlen-1];
7716269Smckusick 	while ((n = getc(fp)) != '\n') {
7816269Smckusick 		if (n == EOF)
7916269Smckusick 			return (EOF);
8016269Smckusick 		if (!isspace(n) && p < lastloc)
8116269Smckusick 			*p++ = n;
8216269Smckusick 	}
8316269Smckusick 	*p = 0;
8416269Smckusick 	return (p - loc);
8516269Smckusick }
8616269Smckusick 
87*34225Smckusick /*
88*34225Smckusick  * Malloc buffers and set up cache.
89*34225Smckusick  */
90*34225Smckusick bufinit()
91*34225Smckusick {
92*34225Smckusick 	register BUFAREA *bp;
93*34225Smckusick 	long bufcnt, i;
94*34225Smckusick 	char *bufp;
95*34225Smckusick 
96*34225Smckusick 	bufp = (char *)malloc(sblock.fs_bsize);
97*34225Smckusick 	if (bufp == 0)
98*34225Smckusick 		errexit("cannot allocate buffer pool\n");
99*34225Smckusick 	cgblk.b_un.b_buf = bufp;
100*34225Smckusick 	initbarea(&cgblk);
101*34225Smckusick 	bufhead.b_next = bufhead.b_prev = &bufhead;
102*34225Smckusick 	bufcnt = MAXBUFSPACE / sblock.fs_bsize;
103*34225Smckusick 	if (bufcnt < MINBUFS)
104*34225Smckusick 		bufcnt = MINBUFS;
105*34225Smckusick 	for (i = 0; i < bufcnt; i++) {
106*34225Smckusick 		bp = (BUFAREA *)malloc(sizeof(BUFAREA));
107*34225Smckusick 		bufp = (char *)malloc(sblock.fs_bsize);
108*34225Smckusick 		if (bp == 0 || bufp == 0) {
109*34225Smckusick 			if (i >= MINBUFS)
110*34225Smckusick 				break;
111*34225Smckusick 			errexit("cannot allocate buffer pool\n");
112*34225Smckusick 		}
113*34225Smckusick 		bp->b_un.b_buf = bufp;
114*34225Smckusick 		bp->b_prev = &bufhead;
115*34225Smckusick 		bp->b_next = bufhead.b_next;
116*34225Smckusick 		bufhead.b_next->b_prev = bp;
117*34225Smckusick 		bufhead.b_next = bp;
118*34225Smckusick 		initbarea(bp);
119*34225Smckusick 	}
120*34225Smckusick }
121*34225Smckusick 
122*34225Smckusick /*
123*34225Smckusick  * Manage a cache of directory blocks.
124*34225Smckusick  */
12516269Smckusick BUFAREA *
126*34225Smckusick getdatablk(blkno, size)
127*34225Smckusick 	daddr_t blkno;
128*34225Smckusick 	long size;
129*34225Smckusick {
130*34225Smckusick 	register BUFAREA *bp;
131*34225Smckusick 
132*34225Smckusick 	for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next)
133*34225Smckusick 		if (bp->b_bno == blkno)
134*34225Smckusick 			goto foundit;
135*34225Smckusick 	for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev)
136*34225Smckusick 		if ((bp->b_flags & B_INUSE) == 0)
137*34225Smckusick 			break;
138*34225Smckusick 	if (bp == &bufhead)
139*34225Smckusick 		errexit("deadlocked buffer pool\n");
140*34225Smckusick 	getblk(bp, blkno, size);
141*34225Smckusick 	/* fall through */
142*34225Smckusick foundit:
143*34225Smckusick 	totalreads++;
144*34225Smckusick 	bp->b_prev->b_next = bp->b_next;
145*34225Smckusick 	bp->b_next->b_prev = bp->b_prev;
146*34225Smckusick 	bp->b_prev = &bufhead;
147*34225Smckusick 	bp->b_next = bufhead.b_next;
148*34225Smckusick 	bufhead.b_next->b_prev = bp;
149*34225Smckusick 	bufhead.b_next = bp;
150*34225Smckusick 	bp->b_flags |= B_INUSE;
151*34225Smckusick 	return (bp);
152*34225Smckusick }
153*34225Smckusick 
154*34225Smckusick BUFAREA *
15516269Smckusick getblk(bp, blk, size)
15616269Smckusick 	register BUFAREA *bp;
15716269Smckusick 	daddr_t blk;
15816269Smckusick 	long size;
15916269Smckusick {
16016269Smckusick 	register struct filecntl *fcp;
16116269Smckusick 	daddr_t dblk;
16216269Smckusick 
16316269Smckusick 	fcp = &dfile;
164*34225Smckusick 	if (bp->b_bno == blk)
16516269Smckusick 		return (bp);
16616269Smckusick 	flush(fcp, bp);
167*34225Smckusick 	diskreads++;
168*34225Smckusick 	bp->b_errs = bread(fcp, bp->b_un.b_buf, fsbtodb(&sblock, blk), size);
169*34225Smckusick 	bp->b_bno = blk;
17021540Smckusick 	bp->b_size = size;
17121540Smckusick 	return (bp);
17216269Smckusick }
17316269Smckusick 
17416269Smckusick flush(fcp, bp)
17516269Smckusick 	struct filecntl *fcp;
17616269Smckusick 	register BUFAREA *bp;
17716269Smckusick {
17817931Smckusick 	register int i, j;
17916269Smckusick 
18017931Smckusick 	if (!bp->b_dirty)
18117931Smckusick 		return;
18221540Smckusick 	if (bp->b_errs != 0)
18330609Skarels 		pfatal("WRITING %sZERO'ED BLOCK %d TO DISK\n",
18430609Skarels 		    (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ",
18530609Skarels 		    bp->b_bno);
18616269Smckusick 	bp->b_dirty = 0;
18721540Smckusick 	bp->b_errs = 0;
18821758Smckusick 	bwrite(fcp, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size);
18917931Smckusick 	if (bp != &sblk)
19017931Smckusick 		return;
19117931Smckusick 	for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
19221758Smckusick 		bwrite(&dfile, (char *)sblock.fs_csp[j],
19317931Smckusick 		    fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
19417931Smckusick 		    sblock.fs_cssize - i < sblock.fs_bsize ?
19517931Smckusick 		    sblock.fs_cssize - i : sblock.fs_bsize);
19617931Smckusick 	}
19716269Smckusick }
19816269Smckusick 
19916269Smckusick rwerr(s, blk)
20016269Smckusick 	char *s;
20116269Smckusick 	daddr_t blk;
20216269Smckusick {
20316269Smckusick 
20416269Smckusick 	if (preen == 0)
20516269Smckusick 		printf("\n");
20616269Smckusick 	pfatal("CANNOT %s: BLK %ld", s, blk);
20716269Smckusick 	if (reply("CONTINUE") == 0)
20816269Smckusick 		errexit("Program terminated\n");
20916269Smckusick }
21016269Smckusick 
21116269Smckusick ckfini()
21216269Smckusick {
213*34225Smckusick 	register BUFAREA *bp;
21416269Smckusick 
21516269Smckusick 	flush(&dfile, &sblk);
21630859Skarels 	if (havesb && sblk.b_bno != SBOFF / dev_bsize &&
21730518Smckusick 	    !preen && reply("UPDATE STANDARD SUPERBLOCK")) {
21830556Smckusick 		sblk.b_bno = SBOFF / dev_bsize;
21916269Smckusick 		sbdirty();
22016269Smckusick 		flush(&dfile, &sblk);
22116269Smckusick 	}
22218002Smckusick 	flush(&dfile, &cgblk);
223*34225Smckusick 	for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev)
224*34225Smckusick 		flush(&dfile, bp);
225*34225Smckusick 	if (debug)
226*34225Smckusick 		printf("cache hit %d of %d (%d%%)\n", totalreads - diskreads,
227*34225Smckusick 		    totalreads, (totalreads - diskreads) * 100 / totalreads);
22816269Smckusick 	(void)close(dfile.rfdes);
22916269Smckusick 	(void)close(dfile.wfdes);
23016269Smckusick }
23116269Smckusick 
23216269Smckusick bread(fcp, buf, blk, size)
23316269Smckusick 	register struct filecntl *fcp;
23416269Smckusick 	char *buf;
23516269Smckusick 	daddr_t blk;
23616269Smckusick 	long size;
23716269Smckusick {
23821540Smckusick 	char *cp;
23921540Smckusick 	int i, errs;
24021540Smckusick 
24130557Smckusick 	if (lseek(fcp->rfdes, blk * dev_bsize, 0) < 0)
24216269Smckusick 		rwerr("SEEK", blk);
24316269Smckusick 	else if (read(fcp->rfdes, buf, (int)size) == size)
24421540Smckusick 		return (0);
24516269Smckusick 	rwerr("READ", blk);
24630557Smckusick 	if (lseek(fcp->rfdes, blk * dev_bsize, 0) < 0)
24721540Smckusick 		rwerr("SEEK", blk);
24821540Smckusick 	errs = 0;
24930463Smckusick 	bzero(buf, size);
25030609Skarels 	printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:");
25130609Skarels 	for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) {
25230609Skarels 		if (read(fcp->rfdes, cp, secsize) < 0) {
25330609Skarels 			lseek(fcp->rfdes, blk * dev_bsize + i + secsize, 0);
25430859Skarels 			if (secsize != dev_bsize && dev_bsize != 1)
25530609Skarels 				printf(" %d (%d),",
25630609Skarels 				    (blk * dev_bsize + i) / secsize,
25730609Skarels 				    blk + i / dev_bsize);
25830609Skarels 			else
25930609Skarels 				printf(" %d,", blk + i / dev_bsize);
26021540Smckusick 			errs++;
26121540Smckusick 		}
26221540Smckusick 	}
26321758Smckusick 	printf("\n");
26421540Smckusick 	return (errs);
26516269Smckusick }
26616269Smckusick 
26716269Smckusick bwrite(fcp, buf, blk, size)
26816269Smckusick 	register struct filecntl *fcp;
26916269Smckusick 	char *buf;
27016269Smckusick 	daddr_t blk;
27116269Smckusick 	long size;
27216269Smckusick {
27321758Smckusick 	int i;
27421758Smckusick 	char *cp;
27516269Smckusick 
27616269Smckusick 	if (fcp->wfdes < 0)
27721758Smckusick 		return;
27830557Smckusick 	if (lseek(fcp->wfdes, blk * dev_bsize, 0) < 0)
27916269Smckusick 		rwerr("SEEK", blk);
28016269Smckusick 	else if (write(fcp->wfdes, buf, (int)size) == size) {
28116269Smckusick 		fcp->mod = 1;
28221758Smckusick 		return;
28316269Smckusick 	}
28416269Smckusick 	rwerr("WRITE", blk);
28530557Smckusick 	if (lseek(fcp->wfdes, blk * dev_bsize, 0) < 0)
28621758Smckusick 		rwerr("SEEK", blk);
28730609Skarels 	printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:");
28830518Smckusick 	for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize)
28930518Smckusick 		if (write(fcp->wfdes, cp, dev_bsize) < 0) {
29030557Smckusick 			lseek(fcp->rfdes, blk * dev_bsize + i + dev_bsize, 0);
29130518Smckusick 			printf(" %d,", blk + i / dev_bsize);
29230395Smckusick 		}
29321758Smckusick 	printf("\n");
29421758Smckusick 	return;
29516269Smckusick }
29616269Smckusick 
29717944Smckusick /*
29817944Smckusick  * allocate a data block with the specified number of fragments
29917944Smckusick  */
30017944Smckusick allocblk(frags)
30117944Smckusick 	int frags;
30217944Smckusick {
30317944Smckusick 	register int i, j, k;
30417944Smckusick 
30517944Smckusick 	if (frags <= 0 || frags > sblock.fs_frag)
30617944Smckusick 		return (0);
30717944Smckusick 	for (i = 0; i < fmax - sblock.fs_frag; i += sblock.fs_frag) {
30817944Smckusick 		for (j = 0; j <= sblock.fs_frag - frags; j++) {
30917944Smckusick 			if (getbmap(i + j))
31017944Smckusick 				continue;
31117944Smckusick 			for (k = 1; k < frags; k++)
31217944Smckusick 				if (getbmap(i + j + k))
31317944Smckusick 					break;
31417944Smckusick 			if (k < frags) {
31517944Smckusick 				j += k;
31617944Smckusick 				continue;
31717944Smckusick 			}
31817944Smckusick 			for (k = 0; k < frags; k++)
31917944Smckusick 				setbmap(i + j + k);
32017944Smckusick 			n_blks += frags;
32117944Smckusick 			return (i + j);
32217944Smckusick 		}
32317944Smckusick 	}
32417944Smckusick 	return (0);
32517944Smckusick }
32617944Smckusick 
32717944Smckusick /*
32817944Smckusick  * Free a previously allocated block
32917944Smckusick  */
33017944Smckusick freeblk(blkno, frags)
33117944Smckusick 	daddr_t blkno;
33217944Smckusick 	int frags;
33317944Smckusick {
33417944Smckusick 	struct inodesc idesc;
33517944Smckusick 
33617944Smckusick 	idesc.id_blkno = blkno;
33717944Smckusick 	idesc.id_numfrags = frags;
33817944Smckusick 	pass4check(&idesc);
33917944Smckusick }
34017944Smckusick 
34117991Smckusick /*
34217991Smckusick  * Find a pathname
34317991Smckusick  */
34417991Smckusick getpathname(namebuf, curdir, ino)
34517991Smckusick 	char *namebuf;
34617991Smckusick 	ino_t curdir, ino;
34717991Smckusick {
34817991Smckusick 	int len;
34917991Smckusick 	register char *cp;
35017991Smckusick 	struct inodesc idesc;
35117991Smckusick 	extern int findname();
35217991Smckusick 
35317991Smckusick 	if (statemap[ino] != DSTATE && statemap[ino] != DFOUND) {
35417991Smckusick 		strcpy(namebuf, "?");
35517991Smckusick 		return;
35617991Smckusick 	}
35717991Smckusick 	bzero(&idesc, sizeof(struct inodesc));
35817991Smckusick 	idesc.id_type = DATA;
35917991Smckusick 	cp = &namebuf[BUFSIZ - 1];
36030354Smckusick 	*cp = '\0';
36117991Smckusick 	if (curdir != ino) {
36217991Smckusick 		idesc.id_parent = curdir;
36317991Smckusick 		goto namelookup;
36417991Smckusick 	}
36517991Smckusick 	while (ino != ROOTINO) {
36617991Smckusick 		idesc.id_number = ino;
36717991Smckusick 		idesc.id_func = findino;
36817991Smckusick 		idesc.id_name = "..";
36930354Smckusick 		if ((ckinode(ginode(ino), &idesc) & FOUND) == 0)
37017991Smckusick 			break;
37117991Smckusick 	namelookup:
37217991Smckusick 		idesc.id_number = idesc.id_parent;
37317991Smckusick 		idesc.id_parent = ino;
37417991Smckusick 		idesc.id_func = findname;
37517991Smckusick 		idesc.id_name = namebuf;
37630354Smckusick 		if ((ckinode(ginode(idesc.id_number), &idesc) & FOUND) == 0)
37717991Smckusick 			break;
37817991Smckusick 		len = strlen(namebuf);
37917991Smckusick 		cp -= len;
38017991Smckusick 		if (cp < &namebuf[MAXNAMLEN])
38117991Smckusick 			break;
38217991Smckusick 		bcopy(namebuf, cp, len);
38317991Smckusick 		*--cp = '/';
38417991Smckusick 		ino = idesc.id_number;
38517991Smckusick 	}
38617991Smckusick 	if (ino != ROOTINO) {
38717991Smckusick 		strcpy(namebuf, "?");
38817991Smckusick 		return;
38917991Smckusick 	}
39017991Smckusick 	bcopy(cp, namebuf, &namebuf[BUFSIZ] - cp);
39117991Smckusick }
39217991Smckusick 
39316269Smckusick catch()
39416269Smckusick {
39516269Smckusick 
39616269Smckusick 	ckfini();
39716269Smckusick 	exit(12);
39816269Smckusick }
39916269Smckusick 
40016269Smckusick /*
40124680Skarels  * When preening, allow a single quit to signal
40224680Skarels  * a special exit after filesystem checks complete
40324680Skarels  * so that reboot sequence may be interrupted.
40424680Skarels  */
40524680Skarels catchquit()
40624680Skarels {
40724680Skarels 	extern returntosingle;
40824680Skarels 
40924680Skarels 	printf("returning to single-user after filesystem check\n");
41024680Skarels 	returntosingle = 1;
41124680Skarels 	(void)signal(SIGQUIT, SIG_DFL);
41224680Skarels }
41324680Skarels 
41424680Skarels /*
41524680Skarels  * Ignore a single quit signal; wait and flush just in case.
41624680Skarels  * Used by child processes in preen.
41724680Skarels  */
41824680Skarels voidquit()
41924680Skarels {
42024680Skarels 
42124680Skarels 	sleep(1);
42224680Skarels 	(void)signal(SIGQUIT, SIG_IGN);
42324680Skarels 	(void)signal(SIGQUIT, SIG_DFL);
42424680Skarels }
42524680Skarels 
42624680Skarels /*
42716269Smckusick  * determine whether an inode should be fixed.
42816269Smckusick  */
42917931Smckusick dofix(idesc, msg)
43016269Smckusick 	register struct inodesc *idesc;
43117931Smckusick 	char *msg;
43216269Smckusick {
43316269Smckusick 
43416269Smckusick 	switch (idesc->id_fix) {
43516269Smckusick 
43616269Smckusick 	case DONTKNOW:
43717931Smckusick 		if (idesc->id_type == DATA)
43817931Smckusick 			direrr(idesc->id_number, msg);
43917931Smckusick 		else
44017931Smckusick 			pwarn(msg);
44117931Smckusick 		if (preen) {
44217931Smckusick 			printf(" (SALVAGED)\n");
44317931Smckusick 			idesc->id_fix = FIX;
44417931Smckusick 			return (ALTERED);
44517931Smckusick 		}
44616269Smckusick 		if (reply("SALVAGE") == 0) {
44716269Smckusick 			idesc->id_fix = NOFIX;
44816269Smckusick 			return (0);
44916269Smckusick 		}
45016269Smckusick 		idesc->id_fix = FIX;
45116269Smckusick 		return (ALTERED);
45216269Smckusick 
45316269Smckusick 	case FIX:
45416269Smckusick 		return (ALTERED);
45516269Smckusick 
45616269Smckusick 	case NOFIX:
45716269Smckusick 		return (0);
45816269Smckusick 
45916269Smckusick 	default:
46016269Smckusick 		errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix);
46116269Smckusick 	}
46216269Smckusick 	/* NOTREACHED */
46316269Smckusick }
46416269Smckusick 
46516269Smckusick /* VARARGS1 */
46617931Smckusick errexit(s1, s2, s3, s4)
46716269Smckusick 	char *s1;
46816269Smckusick {
46916269Smckusick 	printf(s1, s2, s3, s4);
47016269Smckusick 	exit(8);
47116269Smckusick }
47216269Smckusick 
47316269Smckusick /*
47416269Smckusick  * An inconsistency occured which shouldn't during normal operations.
47516269Smckusick  * Die if preening, otherwise just printf.
47616269Smckusick  */
47716269Smckusick /* VARARGS1 */
47816269Smckusick pfatal(s, a1, a2, a3)
47916269Smckusick 	char *s;
48016269Smckusick {
48116269Smckusick 
48216269Smckusick 	if (preen) {
48316269Smckusick 		printf("%s: ", devname);
48416269Smckusick 		printf(s, a1, a2, a3);
48516269Smckusick 		printf("\n");
48617931Smckusick 		printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
48717931Smckusick 			devname);
48817931Smckusick 		exit(8);
48916269Smckusick 	}
49016269Smckusick 	printf(s, a1, a2, a3);
49116269Smckusick }
49216269Smckusick 
49316269Smckusick /*
49416269Smckusick  * Pwarn is like printf when not preening,
49516269Smckusick  * or a warning (preceded by filename) when preening.
49616269Smckusick  */
49716269Smckusick /* VARARGS1 */
49816269Smckusick pwarn(s, a1, a2, a3, a4, a5, a6)
49916269Smckusick 	char *s;
50016269Smckusick {
50116269Smckusick 
50216269Smckusick 	if (preen)
50316269Smckusick 		printf("%s: ", devname);
50416269Smckusick 	printf(s, a1, a2, a3, a4, a5, a6);
50516269Smckusick }
50616269Smckusick 
50716269Smckusick #ifndef lint
50816269Smckusick /*
50916269Smckusick  * Stub for routines from kernel.
51016269Smckusick  */
51116269Smckusick panic(s)
51216269Smckusick 	char *s;
51316269Smckusick {
51416269Smckusick 
51517931Smckusick 	pfatal("INTERNAL INCONSISTENCY:");
51617931Smckusick 	errexit(s);
51716269Smckusick }
51816269Smckusick #endif
519