utilities.c revision 41477
1265236Sken/*
2265236Sken * Copyright (c) 1980, 1986, 1993
3283661Sslm *	The Regents of the University of California.  All rights reserved.
4299265Sslm *
5265236Sken * Redistribution and use in source and binary forms, with or without
6265236Sken * modification, are permitted provided that the following conditions
7265236Sken * are met:
8265236Sken * 1. Redistributions of source code must retain the above copyright
9265236Sken *    notice, this list of conditions and the following disclaimer.
10265236Sken * 2. Redistributions in binary form must reproduce the above copyright
11265236Sken *    notice, this list of conditions and the following disclaimer in the
12265236Sken *    documentation and/or other materials provided with the distribution.
13265236Sken * 3. All advertising materials mentioning features or use of this software
14265236Sken *    must display the following acknowledgement:
15265236Sken *	This product includes software developed by the University of
16265236Sken *	California, Berkeley and its contributors.
17265236Sken * 4. Neither the name of the University nor the names of its contributors
18265236Sken *    may be used to endorse or promote products derived from this software
19265236Sken *    without specific prior written permission.
20265236Sken *
21265236Sken * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22265236Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23265236Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24265236Sken * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25265236Sken * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26265236Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27265236Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28283661Sslm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29283661Sslm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30265236Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31265236Sken * SUCH DAMAGE.
32265236Sken */
33265236Sken
34265236Sken#ifndef lint
35283661Sslm#if 0
36265236Skenstatic const char sccsid[] = "@(#)utilities.c	8.6 (Berkeley) 5/19/95";
37265236Sken#endif
38265236Skenstatic const char rcsid[] =
39265236Sken	"$Id: utilities.c,v 1.8 1998/06/15 07:07:21 charnier Exp $";
40265236Sken#endif /* not lint */
41265236Sken
42265236Sken#include <sys/param.h>
43265236Sken
44265236Sken#include <ufs/ufs/dinode.h>
45265236Sken#include <ufs/ufs/dir.h>
46265236Sken#include <ufs/ffs/fs.h>
47265236Sken
48265236Sken#include <err.h>
49265236Sken#include <string.h>
50265236Sken
51265236Sken#include "fsck.h"
52265236Sken
53265236Skenlong	diskreads, totalreads;	/* Disk cache statistics */
54265236Sken
55265236Skenstatic void rwerror __P((char *mesg, ufs_daddr_t blk));
56265236Sken
57265236Skenint
58265236Skenftypeok(dp)
59265236Sken	struct dinode *dp;
60265236Sken{
61265236Sken	switch (dp->di_mode & IFMT) {
62265236Sken
63265236Sken	case IFDIR:
64265236Sken	case IFREG:
65265236Sken	case IFBLK:
66265236Sken	case IFCHR:
67265236Sken	case IFLNK:
68265236Sken	case IFSOCK:
69265236Sken	case IFIFO:
70265236Sken		return (1);
71265236Sken
72265236Sken	default:
73265236Sken		if (debug)
74265236Sken			printf("bad file type 0%o\n", dp->di_mode);
75265236Sken		return (0);
76265236Sken	}
77265236Sken}
78265236Sken
79265236Skenint
80265236Skenreply(question)
81265236Sken	char *question;
82265236Sken{
83265236Sken	int persevere;
84265236Sken	char c;
85265236Sken
86265236Sken	if (preen)
87265236Sken		pfatal("INTERNAL ERROR: GOT TO reply()");
88265236Sken	persevere = !strcmp(question, "CONTINUE");
89265236Sken	printf("\n");
90265236Sken	if (!persevere && (nflag || fswritefd < 0)) {
91265236Sken		printf("%s? no\n\n", question);
92265236Sken		resolved = 0;
93265236Sken		return (0);
94265236Sken	}
95299265Sslm	if (yflag || (persevere && nflag)) {
96265236Sken		printf("%s? yes\n\n", question);
97265236Sken		return (1);
98299265Sslm	}
99299265Sslm	do	{
100265236Sken		printf("%s? [yn] ", question);
101265236Sken		(void) fflush(stdout);
102265236Sken		c = getc(stdin);
103265236Sken		while (c != '\n' && getc(stdin) != '\n') {
104265236Sken			if (feof(stdin)) {
105265236Sken				resolved = 0;
106265236Sken				return (0);
107265236Sken			}
108265236Sken		}
109265236Sken	} while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
110265236Sken	printf("\n");
111265236Sken	if (c == 'y' || c == 'Y')
112265236Sken		return (1);
113265236Sken	resolved = 0;
114265236Sken	return (0);
115265236Sken}
116265236Sken
117265236Sken/*
118265236Sken * Look up state information for an inode.
119265236Sken */
120265236Skenstruct inostat *
121265236Skeninoinfo(inum)
122265236Sken	ino_t inum;
123265236Sken{
124265236Sken	static struct inostat unallocated = { USTATE, 0, 0 };
125265236Sken	struct inostatlist *ilp;
126265236Sken	int iloff;
127265236Sken
128265236Sken	if (inum > maxino)
129265236Sken		errx(EEXIT, "inoinfo: inumber %d out of range", inum);
130265236Sken	ilp = &inostathead[inum / sblock.fs_ipg];
131265236Sken	iloff = inum % sblock.fs_ipg;
132265236Sken	if (iloff >= ilp->il_numalloced)
133265236Sken		return (&unallocated);
134265236Sken	return (&ilp->il_stat[iloff]);
135265236Sken}
136265236Sken
137265236Sken/*
138265236Sken * Malloc buffers and set up cache.
139265236Sken */
140265236Skenvoid
141265236Skenbufinit()
142265236Sken{
143265236Sken	register struct bufarea *bp;
144265236Sken	long bufcnt, i;
145265236Sken	char *bufp;
146265236Sken
147265236Sken	pbp = pdirbp = (struct bufarea *)0;
148265236Sken	bufp = malloc((unsigned int)sblock.fs_bsize);
149265236Sken	if (bufp == 0)
150265236Sken		errx(EEXIT, "cannot allocate buffer pool");
151265236Sken	cgblk.b_un.b_buf = bufp;
152265236Sken	initbarea(&cgblk);
153265236Sken	bufhead.b_next = bufhead.b_prev = &bufhead;
154265236Sken	bufcnt = MAXBUFSPACE / sblock.fs_bsize;
155265236Sken	if (bufcnt < MINBUFS)
156265236Sken		bufcnt = MINBUFS;
157265236Sken	for (i = 0; i < bufcnt; i++) {
158265236Sken		bp = (struct bufarea *)malloc(sizeof(struct bufarea));
159265236Sken		bufp = malloc((unsigned int)sblock.fs_bsize);
160265236Sken		if (bp == NULL || bufp == NULL) {
161265236Sken			if (i >= MINBUFS)
162265236Sken				break;
163265236Sken			errx(EEXIT, "cannot allocate buffer pool");
164265236Sken		}
165265236Sken		bp->b_un.b_buf = bufp;
166265236Sken		bp->b_prev = &bufhead;
167265236Sken		bp->b_next = bufhead.b_next;
168265236Sken		bufhead.b_next->b_prev = bp;
169265236Sken		bufhead.b_next = bp;
170265236Sken		initbarea(bp);
171265236Sken	}
172265236Sken	bufhead.b_size = i;	/* save number of buffers */
173265236Sken}
174265236Sken
175265236Sken/*
176265236Sken * Manage a cache of directory blocks.
177265236Sken */
178265236Skenstruct bufarea *
179265236Skengetdatablk(blkno, size)
180265236Sken	ufs_daddr_t blkno;
181265236Sken	long size;
182265236Sken{
183265236Sken	register struct bufarea *bp;
184265236Sken
185265236Sken	for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next)
186265236Sken		if (bp->b_bno == fsbtodb(&sblock, blkno))
187265236Sken			goto foundit;
188265236Sken	for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev)
189265236Sken		if ((bp->b_flags & B_INUSE) == 0)
190265236Sken			break;
191265236Sken	if (bp == &bufhead)
192265236Sken		errx(EEXIT, "deadlocked buffer pool");
193265236Sken	getblk(bp, blkno, size);
194265236Sken	/* fall through */
195265236Skenfoundit:
196265236Sken	totalreads++;
197265236Sken	bp->b_prev->b_next = bp->b_next;
198265236Sken	bp->b_next->b_prev = bp->b_prev;
199265236Sken	bp->b_prev = &bufhead;
200265236Sken	bp->b_next = bufhead.b_next;
201265236Sken	bufhead.b_next->b_prev = bp;
202265236Sken	bufhead.b_next = bp;
203265236Sken	bp->b_flags |= B_INUSE;
204265236Sken	return (bp);
205265236Sken}
206265236Sken
207265236Skenvoid
208265236Skengetblk(bp, blk, size)
209265236Sken	register struct bufarea *bp;
210265236Sken	ufs_daddr_t blk;
211265236Sken	long size;
212265236Sken{
213265236Sken	ufs_daddr_t dblk;
214265236Sken
215265236Sken	dblk = fsbtodb(&sblock, blk);
216265236Sken	if (bp->b_bno != dblk) {
217265236Sken		flush(fswritefd, bp);
218265236Sken		diskreads++;
219265236Sken		bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, dblk, size);
220265236Sken		bp->b_bno = dblk;
221265236Sken		bp->b_size = size;
222265236Sken	}
223265236Sken}
224265236Sken
225265236Skenvoid
226265236Skenflush(fd, bp)
227265236Sken	int fd;
228265236Sken	register struct bufarea *bp;
229265236Sken{
230265236Sken	register int i, j;
231265236Sken
232265236Sken	if (!bp->b_dirty)
233265236Sken		return;
234265236Sken	if (bp->b_errs != 0)
235265236Sken		pfatal("WRITING %sZERO'ED BLOCK %d TO DISK\n",
236265236Sken		    (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ",
237265236Sken		    bp->b_bno);
238265236Sken	bp->b_dirty = 0;
239265236Sken	bp->b_errs = 0;
240265236Sken	bwrite(fd, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size);
241265236Sken	if (bp != &sblk)
242265236Sken		return;
243265236Sken	for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
244265236Sken		bwrite(fswritefd, (char *)sblock.fs_csp[j],
245265236Sken		    fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
246265236Sken		    sblock.fs_cssize - i < sblock.fs_bsize ?
247265236Sken		    sblock.fs_cssize - i : sblock.fs_bsize);
248265236Sken	}
249265236Sken}
250265236Sken
251265236Skenstatic void
252265236Skenrwerror(mesg, blk)
253265236Sken	char *mesg;
254265236Sken	ufs_daddr_t blk;
255265236Sken{
256265236Sken
257265236Sken	if (preen == 0)
258265236Sken		printf("\n");
259265236Sken	pfatal("CANNOT %s: BLK %ld", mesg, blk);
260265236Sken	if (reply("CONTINUE") == 0)
261265236Sken		exit(EEXIT);
262265236Sken}
263265236Sken
264265236Skenvoid
265265236Skenckfini(markclean)
266265236Sken	int markclean;
267265236Sken{
268265236Sken	register struct bufarea *bp, *nbp;
269265236Sken	int ofsmodified, cnt = 0;
270265236Sken
271265236Sken	if (fswritefd < 0) {
272265236Sken		(void)close(fsreadfd);
273265236Sken		return;
274265236Sken	}
275265236Sken	flush(fswritefd, &sblk);
276265236Sken	if (havesb && sblk.b_bno != SBOFF / dev_bsize &&
277265236Sken	    !preen && reply("UPDATE STANDARD SUPERBLOCK")) {
278265236Sken		sblk.b_bno = SBOFF / dev_bsize;
279265236Sken		sbdirty();
280265236Sken		flush(fswritefd, &sblk);
281265236Sken	}
282265236Sken	flush(fswritefd, &cgblk);
283265236Sken	free(cgblk.b_un.b_buf);
284265236Sken	for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) {
285265236Sken		cnt++;
286265236Sken		flush(fswritefd, bp);
287265236Sken		nbp = bp->b_prev;
288265236Sken		free(bp->b_un.b_buf);
289265236Sken		free((char *)bp);
290265236Sken	}
291265236Sken	if (bufhead.b_size != cnt)
292265236Sken		errx(EEXIT, "panic: lost %d buffers", bufhead.b_size - cnt);
293265236Sken	pbp = pdirbp = (struct bufarea *)0;
294265236Sken	if (sblock.fs_clean != markclean) {
295265236Sken		sblock.fs_clean = markclean;
296265236Sken		sbdirty();
297265236Sken		ofsmodified = fsmodified;
298265236Sken		flush(fswritefd, &sblk);
299265236Sken		fsmodified = ofsmodified;
300265236Sken		if (!preen) {
301265236Sken			printf("\n***** FILE SYSTEM MARKED %s *****\n",
302265236Sken			    markclean ? "CLEAN" : "DIRTY");
303265236Sken			if (!markclean)
304265236Sken				rerun = 1;
305265236Sken		}
306265236Sken	} else if (!preen && !markclean) {
307265236Sken		printf("\n***** FILE SYSTEM STILL DIRTY *****\n");
308265236Sken		rerun = 1;
309265236Sken	}
310265236Sken	if (debug)
311265236Sken		printf("cache missed %ld of %ld (%d%%)\n", diskreads,
312265236Sken		    totalreads, (int)(diskreads * 100 / totalreads));
313265236Sken	(void)close(fsreadfd);
314265236Sken	(void)close(fswritefd);
315265236Sken}
316265236Sken
317265236Skenint
318265236Skenbread(fd, buf, blk, size)
319265236Sken	int fd;
320265236Sken	char *buf;
321265236Sken	ufs_daddr_t blk;
322265236Sken	long size;
323265236Sken{
324265236Sken	char *cp;
325265236Sken	int i, errs;
326265236Sken	off_t offset;
327265236Sken
328265236Sken	offset = blk;
329265236Sken	offset *= dev_bsize;
330265236Sken	if (lseek(fd, offset, 0) < 0)
331265236Sken		rwerror("SEEK", blk);
332265236Sken	else if (read(fd, buf, (int)size) == size)
333265236Sken		return (0);
334265236Sken	rwerror("READ", blk);
335265236Sken	if (lseek(fd, offset, 0) < 0)
336265236Sken		rwerror("SEEK", blk);
337265236Sken	errs = 0;
338265236Sken	memset(buf, 0, (size_t)size);
339265236Sken	printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:");
340265236Sken	for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) {
341265236Sken		if (read(fd, cp, (int)secsize) != secsize) {
342265236Sken			(void)lseek(fd, offset + i + secsize, 0);
343265236Sken			if (secsize != dev_bsize && dev_bsize != 1)
344265236Sken				printf(" %ld (%ld),",
345265236Sken				    (blk * dev_bsize + i) / secsize,
346265236Sken				    blk + i / dev_bsize);
347265236Sken			else
348265236Sken				printf(" %ld,", blk + i / dev_bsize);
349265236Sken			errs++;
350265236Sken		}
351265236Sken	}
352265236Sken	printf("\n");
353265236Sken	if (errs)
354283661Sslm		resolved = 0;
355265236Sken	return (errs);
356265236Sken}
357265236Sken
358265236Skenvoid
359265236Skenbwrite(fd, buf, blk, size)
360265236Sken	int fd;
361265236Sken	char *buf;
362265236Sken	ufs_daddr_t blk;
363265236Sken	long size;
364265236Sken{
365265236Sken	int i;
366265236Sken	char *cp;
367265236Sken	off_t offset;
368265236Sken
369265236Sken	if (fd < 0)
370265236Sken		return;
371265236Sken	offset = blk;
372265236Sken	offset *= dev_bsize;
373265236Sken	if (lseek(fd, offset, 0) < 0)
374265236Sken		rwerror("SEEK", blk);
375265236Sken	else if (write(fd, buf, (int)size) == size) {
376265236Sken		fsmodified = 1;
377265236Sken		return;
378265236Sken	}
379265236Sken	resolved = 0;
380265236Sken	rwerror("WRITE", blk);
381265236Sken	if (lseek(fd, offset, 0) < 0)
382265236Sken		rwerror("SEEK", blk);
383265236Sken	printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:");
384265236Sken	for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize)
385265236Sken		if (write(fd, cp, (int)dev_bsize) != dev_bsize) {
386265236Sken			(void)lseek(fd, offset + i + dev_bsize, 0);
387265236Sken			printf(" %ld,", blk + i / dev_bsize);
388265236Sken		}
389265236Sken	printf("\n");
390265236Sken	return;
391265236Sken}
392265236Sken
393265236Sken/*
394265236Sken * allocate a data block with the specified number of fragments
395265236Sken */
396265236Skenufs_daddr_t
397265236Skenallocblk(frags)
398265236Sken	long frags;
399265236Sken{
400265236Sken	int i, j, k, cg, baseblk;
401265236Sken	struct cg *cgp = &cgrp;
402265236Sken
403265236Sken	if (frags <= 0 || frags > sblock.fs_frag)
404265236Sken		return (0);
405265236Sken	for (i = 0; i < maxfsblock - sblock.fs_frag; i += sblock.fs_frag) {
406265236Sken		for (j = 0; j <= sblock.fs_frag - frags; j++) {
407265236Sken			if (testbmap(i + j))
408265236Sken				continue;
409265236Sken			for (k = 1; k < frags; k++)
410265236Sken				if (testbmap(i + j + k))
411265236Sken					break;
412265236Sken			if (k < frags) {
413265236Sken				j += k;
414265236Sken				continue;
415265236Sken			}
416265236Sken			cg = dtog(&sblock, i + j);
417265236Sken			getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize);
418265236Sken			if (!cg_chkmagic(cgp))
419265236Sken				pfatal("CG %d: BAD MAGIC NUMBER\n", cg);
420265236Sken			baseblk = dtogd(&sblock, i + j);
421265236Sken			for (k = 0; k < frags; k++) {
422265236Sken				setbmap(i + j + k);
423265236Sken				clrbit(cg_blksfree(cgp), baseblk + k);
424265236Sken			}
425265236Sken			n_blks += frags;
426265236Sken			if (frags == sblock.fs_frag)
427265236Sken				cgp->cg_cs.cs_nbfree--;
428265236Sken			else
429265236Sken				cgp->cg_cs.cs_nffree -= frags;
430265236Sken			cgdirty();
431265236Sken			return (i + j);
432265236Sken		}
433265236Sken	}
434265236Sken	return (0);
435265236Sken}
436265236Sken
437265236Sken/*
438265236Sken * Free a previously allocated block
439265236Sken */
440265236Skenvoid
441265236Skenfreeblk(blkno, frags)
442265236Sken	ufs_daddr_t blkno;
443265236Sken	long frags;
444299266Sslm{
445299266Sslm	struct inodesc idesc;
446265236Sken
447265236Sken	idesc.id_blkno = blkno;
448265236Sken	idesc.id_numfrags = frags;
449265236Sken	(void)pass4check(&idesc);
450265236Sken}
451265236Sken
452265236Sken/*
453265236Sken * Find a pathname
454265236Sken */
455265236Skenvoid
456265236Skengetpathname(namebuf, curdir, ino)
457265236Sken	char *namebuf;
458265236Sken	ino_t curdir, ino;
459265236Sken{
460265236Sken	int len;
461265236Sken	register char *cp;
462265236Sken	struct inodesc idesc;
463265236Sken	static int busy = 0;
464265236Sken
465265236Sken	if (curdir == ino && ino == ROOTINO) {
466265236Sken		(void)strcpy(namebuf, "/");
467265236Sken		return;
468265236Sken	}
469265236Sken	if (busy ||
470265236Sken	    (inoinfo(curdir)->ino_state != DSTATE &&
471265236Sken	     inoinfo(curdir)->ino_state != DFOUND)) {
472265236Sken		(void)strcpy(namebuf, "?");
473265236Sken		return;
474265236Sken	}
475265236Sken	busy = 1;
476265236Sken	memset(&idesc, 0, sizeof(struct inodesc));
477265236Sken	idesc.id_type = DATA;
478265236Sken	idesc.id_fix = IGNORE;
479265236Sken	cp = &namebuf[MAXPATHLEN - 1];
480265236Sken	*cp = '\0';
481265236Sken	if (curdir != ino) {
482265236Sken		idesc.id_parent = curdir;
483265236Sken		goto namelookup;
484265236Sken	}
485265236Sken	while (ino != ROOTINO) {
486265236Sken		idesc.id_number = ino;
487265236Sken		idesc.id_func = findino;
488265236Sken		idesc.id_name = "..";
489265236Sken		if ((ckinode(ginode(ino), &idesc) & FOUND) == 0)
490265236Sken			break;
491265236Sken	namelookup:
492265236Sken		idesc.id_number = idesc.id_parent;
493265236Sken		idesc.id_parent = ino;
494265236Sken		idesc.id_func = findname;
495265236Sken		idesc.id_name = namebuf;
496265236Sken		if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0)
497265236Sken			break;
498265236Sken		len = strlen(namebuf);
499265236Sken		cp -= len;
500265236Sken		memmove(cp, namebuf, (size_t)len);
501265236Sken		*--cp = '/';
502265236Sken		if (cp < &namebuf[MAXNAMLEN])
503265236Sken			break;
504265236Sken		ino = idesc.id_number;
505265236Sken	}
506265236Sken	busy = 0;
507265236Sken	if (ino != ROOTINO)
508265236Sken		*--cp = '?';
509265236Sken	memmove(namebuf, cp, (size_t)(&namebuf[MAXPATHLEN] - cp));
510265236Sken}
511265236Sken
512265236Skenvoid
513265236Skencatch(sig)
514265236Sken	int sig;
515283661Sslm{
516265236Sken	if (!doinglevel2)
517265236Sken		ckfini(0);
518265236Sken	exit(12);
519265236Sken}
520265236Sken
521265236Sken/*
522265236Sken * When preening, allow a single quit to signal
523265236Sken * a special exit after filesystem checks complete
524265236Sken * so that reboot sequence may be interrupted.
525265236Sken */
526265236Skenvoid
527265236Skencatchquit(sig)
528265236Sken	int sig;
529265236Sken{
530265236Sken	printf("returning to single-user after filesystem check\n");
531265236Sken	returntosingle = 1;
532265236Sken	(void)signal(SIGQUIT, SIG_DFL);
533265236Sken}
534265236Sken
535265236Sken/*
536265236Sken * Ignore a single quit signal; wait and flush just in case.
537265236Sken * Used by child processes in preen.
538265236Sken */
539265236Skenvoid
540265236Skenvoidquit(sig)
541265236Sken	int sig;
542265236Sken{
543265236Sken
544265236Sken	sleep(1);
545265236Sken	(void)signal(SIGQUIT, SIG_IGN);
546265236Sken	(void)signal(SIGQUIT, SIG_DFL);
547265236Sken}
548265236Sken
549265236Sken/*
550265236Sken * determine whether an inode should be fixed.
551265236Sken */
552299265Sslmint
553299265Sslmdofix(idesc, msg)
554265236Sken	register struct inodesc *idesc;
555265236Sken	char *msg;
556265236Sken{
557265236Sken
558265236Sken	switch (idesc->id_fix) {
559265236Sken
560265236Sken	case DONTKNOW:
561265236Sken		if (idesc->id_type == DATA)
562265236Sken			direrror(idesc->id_number, msg);
563265236Sken		else
564265236Sken			pwarn(msg);
565265236Sken		if (preen) {
566265236Sken			printf(" (SALVAGED)\n");
567265236Sken			idesc->id_fix = FIX;
568265236Sken			return (ALTERED);
569265236Sken		}
570265236Sken		if (reply("SALVAGE") == 0) {
571265236Sken			idesc->id_fix = NOFIX;
572265236Sken			return (0);
573265236Sken		}
574265236Sken		idesc->id_fix = FIX;
575265236Sken		return (ALTERED);
576265236Sken
577265236Sken	case FIX:
578265236Sken		return (ALTERED);
579265236Sken
580265236Sken	case NOFIX:
581265236Sken	case IGNORE:
582265236Sken		return (0);
583265236Sken
584265236Sken	default:
585265236Sken		errx(EEXIT, "UNKNOWN INODESC FIX MODE %d", idesc->id_fix);
586265236Sken	}
587265236Sken	/* NOTREACHED */
588265236Sken	return (0);
589265236Sken}
590265236Sken
591265236Sken#if __STDC__
592265236Sken#include <stdarg.h>
593265236Sken#else
594265236Sken#include <varargs.h>
595265236Sken#endif
596265236Sken
597265236Sken/*
598265236Sken * An unexpected inconsistency occured.
599265236Sken * Die if preening or filesystem is running with soft dependency protocol,
600265236Sken * otherwise just print message and continue.
601265236Sken */
602265236Skenvoid
603265236Sken#if __STDC__
604265236Skenpfatal(const char *fmt, ...)
605265236Sken#else
606265236Skenpfatal(fmt, va_alist)
607265236Sken	char *fmt;
608265236Sken	va_dcl
609265236Sken#endif
610265236Sken{
611265236Sken	va_list ap;
612265236Sken#if __STDC__
613265236Sken	va_start(ap, fmt);
614265236Sken#else
615265236Sken	va_start(ap);
616265236Sken#endif
617265236Sken	if (!preen) {
618265236Sken		(void)vfprintf(stderr, fmt, ap);
619265236Sken		va_end(ap);
620265236Sken		if (usedsoftdep)
621265236Sken			(void)fprintf(stderr,
622265236Sken			    "\nUNEXPECTED SOFT UPDATE INCONSISTENCY\n");
623265236Sken		return;
624265236Sken	}
625265236Sken	if (cdevname == NULL)
626265236Sken		cdevname = "fsck";
627265236Sken	(void)fprintf(stderr, "%s: ", cdevname);
628265236Sken	(void)vfprintf(stderr, fmt, ap);
629265236Sken	(void)fprintf(stderr,
630265236Sken	    "\n%s: UNEXPECTED%sINCONSISTENCY; RUN fsck MANUALLY.\n",
631265236Sken	    cdevname, usedsoftdep ? " SOFT UPDATE " : " ");
632265236Sken	ckfini(0);
633265236Sken	exit(EEXIT);
634265236Sken}
635265236Sken
636265236Sken/*
637265236Sken * Pwarn just prints a message when not preening or running soft dependency
638265236Sken * protocol, or a warning (preceded by filename) when preening.
639265236Sken */
640265236Skenvoid
641265236Sken#if __STDC__
642265236Skenpwarn(const char *fmt, ...)
643265236Sken#else
644265236Skenpwarn(fmt, va_alist)
645265236Sken	char *fmt;
646265236Sken	va_dcl
647265236Sken#endif
648265236Sken{
649265236Sken	va_list ap;
650265236Sken#if __STDC__
651265236Sken	va_start(ap, fmt);
652265236Sken#else
653265236Sken	va_start(ap);
654265236Sken#endif
655265236Sken	if (preen)
656265236Sken		(void)fprintf(stderr, "%s: ", cdevname);
657265236Sken	(void)vfprintf(stderr, fmt, ap);
658265236Sken	va_end(ap);
659265236Sken}
660265236Sken
661265236Sken/*
662265236Sken * Stub for routines from kernel.
663265236Sken */
664265236Skenvoid
665265236Sken#if __STDC__
666265236Skenpanic(const char *fmt, ...)
667265236Sken#else
668265236Skenpanic(fmt, va_alist)
669265236Sken	char *fmt;
670265236Sken	va_dcl
671265236Sken#endif
672265236Sken{
673265236Sken	va_list ap;
674265236Sken#if __STDC__
675265236Sken	va_start(ap, fmt);
676265236Sken#else
677265236Sken	va_start(ap);
678265236Sken#endif
679265236Sken	pfatal("INTERNAL INCONSISTENCY:");
680265236Sken	(void)vfprintf(stderr, fmt, ap);
681265236Sken	va_end(ap);
682265236Sken	exit(EEXIT);
683265236Sken}
684265236Sken