xref: /freebsd/sbin/fsck_ffs/utilities.c (revision 8fae3551ec46402adf7ab034cf9e02bcbc7ca8ee)
18fae3551SRodney W. Grimes /*
28fae3551SRodney W. Grimes  * Copyright (c) 1980, 1986, 1993
38fae3551SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
48fae3551SRodney W. Grimes  *
58fae3551SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
68fae3551SRodney W. Grimes  * modification, are permitted provided that the following conditions
78fae3551SRodney W. Grimes  * are met:
88fae3551SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
98fae3551SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
108fae3551SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
118fae3551SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
128fae3551SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
138fae3551SRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
148fae3551SRodney W. Grimes  *    must display the following acknowledgement:
158fae3551SRodney W. Grimes  *	This product includes software developed by the University of
168fae3551SRodney W. Grimes  *	California, Berkeley and its contributors.
178fae3551SRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
188fae3551SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
198fae3551SRodney W. Grimes  *    without specific prior written permission.
208fae3551SRodney W. Grimes  *
218fae3551SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
228fae3551SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
238fae3551SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
248fae3551SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
258fae3551SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
268fae3551SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
278fae3551SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
288fae3551SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
298fae3551SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
308fae3551SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
318fae3551SRodney W. Grimes  * SUCH DAMAGE.
328fae3551SRodney W. Grimes  */
338fae3551SRodney W. Grimes 
348fae3551SRodney W. Grimes #ifndef lint
358fae3551SRodney W. Grimes static char sccsid[] = "@(#)utilities.c	8.1 (Berkeley) 6/5/93";
368fae3551SRodney W. Grimes #endif /* not lint */
378fae3551SRodney W. Grimes 
388fae3551SRodney W. Grimes #include <sys/param.h>
398fae3551SRodney W. Grimes #include <sys/time.h>
408fae3551SRodney W. Grimes #include <ufs/ufs/dinode.h>
418fae3551SRodney W. Grimes #include <ufs/ufs/dir.h>
428fae3551SRodney W. Grimes #include <ufs/ffs/fs.h>
438fae3551SRodney W. Grimes #include <stdio.h>
448fae3551SRodney W. Grimes #include <stdlib.h>
458fae3551SRodney W. Grimes #include <string.h>
468fae3551SRodney W. Grimes #include <ctype.h>
478fae3551SRodney W. Grimes #include "fsck.h"
488fae3551SRodney W. Grimes 
498fae3551SRodney W. Grimes long	diskreads, totalreads;	/* Disk cache statistics */
508fae3551SRodney W. Grimes 
518fae3551SRodney W. Grimes ftypeok(dp)
528fae3551SRodney W. Grimes 	struct dinode *dp;
538fae3551SRodney W. Grimes {
548fae3551SRodney W. Grimes 	switch (dp->di_mode & IFMT) {
558fae3551SRodney W. Grimes 
568fae3551SRodney W. Grimes 	case IFDIR:
578fae3551SRodney W. Grimes 	case IFREG:
588fae3551SRodney W. Grimes 	case IFBLK:
598fae3551SRodney W. Grimes 	case IFCHR:
608fae3551SRodney W. Grimes 	case IFLNK:
618fae3551SRodney W. Grimes 	case IFSOCK:
628fae3551SRodney W. Grimes 	case IFIFO:
638fae3551SRodney W. Grimes 		return (1);
648fae3551SRodney W. Grimes 
658fae3551SRodney W. Grimes 	default:
668fae3551SRodney W. Grimes 		if (debug)
678fae3551SRodney W. Grimes 			printf("bad file type 0%o\n", dp->di_mode);
688fae3551SRodney W. Grimes 		return (0);
698fae3551SRodney W. Grimes 	}
708fae3551SRodney W. Grimes }
718fae3551SRodney W. Grimes 
728fae3551SRodney W. Grimes reply(question)
738fae3551SRodney W. Grimes 	char *question;
748fae3551SRodney W. Grimes {
758fae3551SRodney W. Grimes 	int persevere;
768fae3551SRodney W. Grimes 	char c;
778fae3551SRodney W. Grimes 
788fae3551SRodney W. Grimes 	if (preen)
798fae3551SRodney W. Grimes 		pfatal("INTERNAL ERROR: GOT TO reply()");
808fae3551SRodney W. Grimes 	persevere = !strcmp(question, "CONTINUE");
818fae3551SRodney W. Grimes 	printf("\n");
828fae3551SRodney W. Grimes 	if (!persevere && (nflag || fswritefd < 0)) {
838fae3551SRodney W. Grimes 		printf("%s? no\n\n", question);
848fae3551SRodney W. Grimes 		return (0);
858fae3551SRodney W. Grimes 	}
868fae3551SRodney W. Grimes 	if (yflag || (persevere && nflag)) {
878fae3551SRodney W. Grimes 		printf("%s? yes\n\n", question);
888fae3551SRodney W. Grimes 		return (1);
898fae3551SRodney W. Grimes 	}
908fae3551SRodney W. Grimes 	do	{
918fae3551SRodney W. Grimes 		printf("%s? [yn] ", question);
928fae3551SRodney W. Grimes 		(void) fflush(stdout);
938fae3551SRodney W. Grimes 		c = getc(stdin);
948fae3551SRodney W. Grimes 		while (c != '\n' && getc(stdin) != '\n')
958fae3551SRodney W. Grimes 			if (feof(stdin))
968fae3551SRodney W. Grimes 				return (0);
978fae3551SRodney W. Grimes 	} while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
988fae3551SRodney W. Grimes 	printf("\n");
998fae3551SRodney W. Grimes 	if (c == 'y' || c == 'Y')
1008fae3551SRodney W. Grimes 		return (1);
1018fae3551SRodney W. Grimes 	return (0);
1028fae3551SRodney W. Grimes }
1038fae3551SRodney W. Grimes 
1048fae3551SRodney W. Grimes /*
1058fae3551SRodney W. Grimes  * Malloc buffers and set up cache.
1068fae3551SRodney W. Grimes  */
1078fae3551SRodney W. Grimes bufinit()
1088fae3551SRodney W. Grimes {
1098fae3551SRodney W. Grimes 	register struct bufarea *bp;
1108fae3551SRodney W. Grimes 	long bufcnt, i;
1118fae3551SRodney W. Grimes 	char *bufp;
1128fae3551SRodney W. Grimes 
1138fae3551SRodney W. Grimes 	pbp = pdirbp = (struct bufarea *)0;
1148fae3551SRodney W. Grimes 	bufp = malloc((unsigned int)sblock.fs_bsize);
1158fae3551SRodney W. Grimes 	if (bufp == 0)
1168fae3551SRodney W. Grimes 		errexit("cannot allocate buffer pool\n");
1178fae3551SRodney W. Grimes 	cgblk.b_un.b_buf = bufp;
1188fae3551SRodney W. Grimes 	initbarea(&cgblk);
1198fae3551SRodney W. Grimes 	bufhead.b_next = bufhead.b_prev = &bufhead;
1208fae3551SRodney W. Grimes 	bufcnt = MAXBUFSPACE / sblock.fs_bsize;
1218fae3551SRodney W. Grimes 	if (bufcnt < MINBUFS)
1228fae3551SRodney W. Grimes 		bufcnt = MINBUFS;
1238fae3551SRodney W. Grimes 	for (i = 0; i < bufcnt; i++) {
1248fae3551SRodney W. Grimes 		bp = (struct bufarea *)malloc(sizeof(struct bufarea));
1258fae3551SRodney W. Grimes 		bufp = malloc((unsigned int)sblock.fs_bsize);
1268fae3551SRodney W. Grimes 		if (bp == NULL || bufp == NULL) {
1278fae3551SRodney W. Grimes 			if (i >= MINBUFS)
1288fae3551SRodney W. Grimes 				break;
1298fae3551SRodney W. Grimes 			errexit("cannot allocate buffer pool\n");
1308fae3551SRodney W. Grimes 		}
1318fae3551SRodney W. Grimes 		bp->b_un.b_buf = bufp;
1328fae3551SRodney W. Grimes 		bp->b_prev = &bufhead;
1338fae3551SRodney W. Grimes 		bp->b_next = bufhead.b_next;
1348fae3551SRodney W. Grimes 		bufhead.b_next->b_prev = bp;
1358fae3551SRodney W. Grimes 		bufhead.b_next = bp;
1368fae3551SRodney W. Grimes 		initbarea(bp);
1378fae3551SRodney W. Grimes 	}
1388fae3551SRodney W. Grimes 	bufhead.b_size = i;	/* save number of buffers */
1398fae3551SRodney W. Grimes }
1408fae3551SRodney W. Grimes 
1418fae3551SRodney W. Grimes /*
1428fae3551SRodney W. Grimes  * Manage a cache of directory blocks.
1438fae3551SRodney W. Grimes  */
1448fae3551SRodney W. Grimes struct bufarea *
1458fae3551SRodney W. Grimes getdatablk(blkno, size)
1468fae3551SRodney W. Grimes 	daddr_t blkno;
1478fae3551SRodney W. Grimes 	long size;
1488fae3551SRodney W. Grimes {
1498fae3551SRodney W. Grimes 	register struct bufarea *bp;
1508fae3551SRodney W. Grimes 
1518fae3551SRodney W. Grimes 	for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next)
1528fae3551SRodney W. Grimes 		if (bp->b_bno == fsbtodb(&sblock, blkno))
1538fae3551SRodney W. Grimes 			goto foundit;
1548fae3551SRodney W. Grimes 	for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev)
1558fae3551SRodney W. Grimes 		if ((bp->b_flags & B_INUSE) == 0)
1568fae3551SRodney W. Grimes 			break;
1578fae3551SRodney W. Grimes 	if (bp == &bufhead)
1588fae3551SRodney W. Grimes 		errexit("deadlocked buffer pool\n");
1598fae3551SRodney W. Grimes 	getblk(bp, blkno, size);
1608fae3551SRodney W. Grimes 	/* fall through */
1618fae3551SRodney W. Grimes foundit:
1628fae3551SRodney W. Grimes 	totalreads++;
1638fae3551SRodney W. Grimes 	bp->b_prev->b_next = bp->b_next;
1648fae3551SRodney W. Grimes 	bp->b_next->b_prev = bp->b_prev;
1658fae3551SRodney W. Grimes 	bp->b_prev = &bufhead;
1668fae3551SRodney W. Grimes 	bp->b_next = bufhead.b_next;
1678fae3551SRodney W. Grimes 	bufhead.b_next->b_prev = bp;
1688fae3551SRodney W. Grimes 	bufhead.b_next = bp;
1698fae3551SRodney W. Grimes 	bp->b_flags |= B_INUSE;
1708fae3551SRodney W. Grimes 	return (bp);
1718fae3551SRodney W. Grimes }
1728fae3551SRodney W. Grimes 
1738fae3551SRodney W. Grimes void
1748fae3551SRodney W. Grimes getblk(bp, blk, size)
1758fae3551SRodney W. Grimes 	register struct bufarea *bp;
1768fae3551SRodney W. Grimes 	daddr_t blk;
1778fae3551SRodney W. Grimes 	long size;
1788fae3551SRodney W. Grimes {
1798fae3551SRodney W. Grimes 	daddr_t dblk;
1808fae3551SRodney W. Grimes 
1818fae3551SRodney W. Grimes 	dblk = fsbtodb(&sblock, blk);
1828fae3551SRodney W. Grimes 	if (bp->b_bno != dblk) {
1838fae3551SRodney W. Grimes 		flush(fswritefd, bp);
1848fae3551SRodney W. Grimes 		diskreads++;
1858fae3551SRodney W. Grimes 		bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, dblk, size);
1868fae3551SRodney W. Grimes 		bp->b_bno = dblk;
1878fae3551SRodney W. Grimes 		bp->b_size = size;
1888fae3551SRodney W. Grimes 	}
1898fae3551SRodney W. Grimes }
1908fae3551SRodney W. Grimes 
1918fae3551SRodney W. Grimes flush(fd, bp)
1928fae3551SRodney W. Grimes 	int fd;
1938fae3551SRodney W. Grimes 	register struct bufarea *bp;
1948fae3551SRodney W. Grimes {
1958fae3551SRodney W. Grimes 	register int i, j;
1968fae3551SRodney W. Grimes 
1978fae3551SRodney W. Grimes 	if (!bp->b_dirty)
1988fae3551SRodney W. Grimes 		return;
1998fae3551SRodney W. Grimes 	if (bp->b_errs != 0)
2008fae3551SRodney W. Grimes 		pfatal("WRITING %sZERO'ED BLOCK %d TO DISK\n",
2018fae3551SRodney W. Grimes 		    (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ",
2028fae3551SRodney W. Grimes 		    bp->b_bno);
2038fae3551SRodney W. Grimes 	bp->b_dirty = 0;
2048fae3551SRodney W. Grimes 	bp->b_errs = 0;
2058fae3551SRodney W. Grimes 	bwrite(fd, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size);
2068fae3551SRodney W. Grimes 	if (bp != &sblk)
2078fae3551SRodney W. Grimes 		return;
2088fae3551SRodney W. Grimes 	for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
2098fae3551SRodney W. Grimes 		bwrite(fswritefd, (char *)sblock.fs_csp[j],
2108fae3551SRodney W. Grimes 		    fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
2118fae3551SRodney W. Grimes 		    sblock.fs_cssize - i < sblock.fs_bsize ?
2128fae3551SRodney W. Grimes 		    sblock.fs_cssize - i : sblock.fs_bsize);
2138fae3551SRodney W. Grimes 	}
2148fae3551SRodney W. Grimes }
2158fae3551SRodney W. Grimes 
2168fae3551SRodney W. Grimes rwerror(mesg, blk)
2178fae3551SRodney W. Grimes 	char *mesg;
2188fae3551SRodney W. Grimes 	daddr_t blk;
2198fae3551SRodney W. Grimes {
2208fae3551SRodney W. Grimes 
2218fae3551SRodney W. Grimes 	if (preen == 0)
2228fae3551SRodney W. Grimes 		printf("\n");
2238fae3551SRodney W. Grimes 	pfatal("CANNOT %s: BLK %ld", mesg, blk);
2248fae3551SRodney W. Grimes 	if (reply("CONTINUE") == 0)
2258fae3551SRodney W. Grimes 		errexit("Program terminated\n");
2268fae3551SRodney W. Grimes }
2278fae3551SRodney W. Grimes 
2288fae3551SRodney W. Grimes ckfini()
2298fae3551SRodney W. Grimes {
2308fae3551SRodney W. Grimes 	register struct bufarea *bp, *nbp;
2318fae3551SRodney W. Grimes 	int cnt = 0;
2328fae3551SRodney W. Grimes 
2338fae3551SRodney W. Grimes 	if (fswritefd < 0) {
2348fae3551SRodney W. Grimes 		(void)close(fsreadfd);
2358fae3551SRodney W. Grimes 		return;
2368fae3551SRodney W. Grimes 	}
2378fae3551SRodney W. Grimes 	flush(fswritefd, &sblk);
2388fae3551SRodney W. Grimes 	if (havesb && sblk.b_bno != SBOFF / dev_bsize &&
2398fae3551SRodney W. Grimes 	    !preen && reply("UPDATE STANDARD SUPERBLOCK")) {
2408fae3551SRodney W. Grimes 		sblk.b_bno = SBOFF / dev_bsize;
2418fae3551SRodney W. Grimes 		sbdirty();
2428fae3551SRodney W. Grimes 		flush(fswritefd, &sblk);
2438fae3551SRodney W. Grimes 	}
2448fae3551SRodney W. Grimes 	flush(fswritefd, &cgblk);
2458fae3551SRodney W. Grimes 	free(cgblk.b_un.b_buf);
2468fae3551SRodney W. Grimes 	for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) {
2478fae3551SRodney W. Grimes 		cnt++;
2488fae3551SRodney W. Grimes 		flush(fswritefd, bp);
2498fae3551SRodney W. Grimes 		nbp = bp->b_prev;
2508fae3551SRodney W. Grimes 		free(bp->b_un.b_buf);
2518fae3551SRodney W. Grimes 		free((char *)bp);
2528fae3551SRodney W. Grimes 	}
2538fae3551SRodney W. Grimes 	if (bufhead.b_size != cnt)
2548fae3551SRodney W. Grimes 		errexit("Panic: lost %d buffers\n", bufhead.b_size - cnt);
2558fae3551SRodney W. Grimes 	pbp = pdirbp = (struct bufarea *)0;
2568fae3551SRodney W. Grimes 	if (debug)
2578fae3551SRodney W. Grimes 		printf("cache missed %ld of %ld (%d%%)\n", diskreads,
2588fae3551SRodney W. Grimes 		    totalreads, (int)(diskreads * 100 / totalreads));
2598fae3551SRodney W. Grimes 	(void)close(fsreadfd);
2608fae3551SRodney W. Grimes 	(void)close(fswritefd);
2618fae3551SRodney W. Grimes }
2628fae3551SRodney W. Grimes 
2638fae3551SRodney W. Grimes bread(fd, buf, blk, size)
2648fae3551SRodney W. Grimes 	int fd;
2658fae3551SRodney W. Grimes 	char *buf;
2668fae3551SRodney W. Grimes 	daddr_t blk;
2678fae3551SRodney W. Grimes 	long size;
2688fae3551SRodney W. Grimes {
2698fae3551SRodney W. Grimes 	char *cp;
2708fae3551SRodney W. Grimes 	int i, errs;
2718fae3551SRodney W. Grimes 	off_t offset;
2728fae3551SRodney W. Grimes 
2738fae3551SRodney W. Grimes 	offset = blk;
2748fae3551SRodney W. Grimes 	offset *= dev_bsize;
2758fae3551SRodney W. Grimes 	if (lseek(fd, offset, 0) < 0)
2768fae3551SRodney W. Grimes 		rwerror("SEEK", blk);
2778fae3551SRodney W. Grimes 	else if (read(fd, buf, (int)size) == size)
2788fae3551SRodney W. Grimes 		return (0);
2798fae3551SRodney W. Grimes 	rwerror("READ", blk);
2808fae3551SRodney W. Grimes 	if (lseek(fd, offset, 0) < 0)
2818fae3551SRodney W. Grimes 		rwerror("SEEK", blk);
2828fae3551SRodney W. Grimes 	errs = 0;
2838fae3551SRodney W. Grimes 	bzero(buf, (size_t)size);
2848fae3551SRodney W. Grimes 	printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:");
2858fae3551SRodney W. Grimes 	for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) {
2868fae3551SRodney W. Grimes 		if (read(fd, cp, (int)secsize) != secsize) {
2878fae3551SRodney W. Grimes 			(void)lseek(fd, offset + i + secsize, 0);
2888fae3551SRodney W. Grimes 			if (secsize != dev_bsize && dev_bsize != 1)
2898fae3551SRodney W. Grimes 				printf(" %ld (%ld),",
2908fae3551SRodney W. Grimes 				    (blk * dev_bsize + i) / secsize,
2918fae3551SRodney W. Grimes 				    blk + i / dev_bsize);
2928fae3551SRodney W. Grimes 			else
2938fae3551SRodney W. Grimes 				printf(" %ld,", blk + i / dev_bsize);
2948fae3551SRodney W. Grimes 			errs++;
2958fae3551SRodney W. Grimes 		}
2968fae3551SRodney W. Grimes 	}
2978fae3551SRodney W. Grimes 	printf("\n");
2988fae3551SRodney W. Grimes 	return (errs);
2998fae3551SRodney W. Grimes }
3008fae3551SRodney W. Grimes 
3018fae3551SRodney W. Grimes bwrite(fd, buf, blk, size)
3028fae3551SRodney W. Grimes 	int fd;
3038fae3551SRodney W. Grimes 	char *buf;
3048fae3551SRodney W. Grimes 	daddr_t blk;
3058fae3551SRodney W. Grimes 	long size;
3068fae3551SRodney W. Grimes {
3078fae3551SRodney W. Grimes 	int i;
3088fae3551SRodney W. Grimes 	char *cp;
3098fae3551SRodney W. Grimes 	off_t offset;
3108fae3551SRodney W. Grimes 
3118fae3551SRodney W. Grimes 	if (fd < 0)
3128fae3551SRodney W. Grimes 		return;
3138fae3551SRodney W. Grimes 	offset = blk;
3148fae3551SRodney W. Grimes 	offset *= dev_bsize;
3158fae3551SRodney W. Grimes 	if (lseek(fd, offset, 0) < 0)
3168fae3551SRodney W. Grimes 		rwerror("SEEK", blk);
3178fae3551SRodney W. Grimes 	else if (write(fd, buf, (int)size) == size) {
3188fae3551SRodney W. Grimes 		fsmodified = 1;
3198fae3551SRodney W. Grimes 		return;
3208fae3551SRodney W. Grimes 	}
3218fae3551SRodney W. Grimes 	rwerror("WRITE", blk);
3228fae3551SRodney W. Grimes 	if (lseek(fd, offset, 0) < 0)
3238fae3551SRodney W. Grimes 		rwerror("SEEK", blk);
3248fae3551SRodney W. Grimes 	printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:");
3258fae3551SRodney W. Grimes 	for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize)
3268fae3551SRodney W. Grimes 		if (write(fd, cp, (int)dev_bsize) != dev_bsize) {
3278fae3551SRodney W. Grimes 			(void)lseek(fd, offset + i + dev_bsize, 0);
3288fae3551SRodney W. Grimes 			printf(" %ld,", blk + i / dev_bsize);
3298fae3551SRodney W. Grimes 		}
3308fae3551SRodney W. Grimes 	printf("\n");
3318fae3551SRodney W. Grimes 	return;
3328fae3551SRodney W. Grimes }
3338fae3551SRodney W. Grimes 
3348fae3551SRodney W. Grimes /*
3358fae3551SRodney W. Grimes  * allocate a data block with the specified number of fragments
3368fae3551SRodney W. Grimes  */
3378fae3551SRodney W. Grimes allocblk(frags)
3388fae3551SRodney W. Grimes 	long frags;
3398fae3551SRodney W. Grimes {
3408fae3551SRodney W. Grimes 	register int i, j, k;
3418fae3551SRodney W. Grimes 
3428fae3551SRodney W. Grimes 	if (frags <= 0 || frags > sblock.fs_frag)
3438fae3551SRodney W. Grimes 		return (0);
3448fae3551SRodney W. Grimes 	for (i = 0; i < maxfsblock - sblock.fs_frag; i += sblock.fs_frag) {
3458fae3551SRodney W. Grimes 		for (j = 0; j <= sblock.fs_frag - frags; j++) {
3468fae3551SRodney W. Grimes 			if (testbmap(i + j))
3478fae3551SRodney W. Grimes 				continue;
3488fae3551SRodney W. Grimes 			for (k = 1; k < frags; k++)
3498fae3551SRodney W. Grimes 				if (testbmap(i + j + k))
3508fae3551SRodney W. Grimes 					break;
3518fae3551SRodney W. Grimes 			if (k < frags) {
3528fae3551SRodney W. Grimes 				j += k;
3538fae3551SRodney W. Grimes 				continue;
3548fae3551SRodney W. Grimes 			}
3558fae3551SRodney W. Grimes 			for (k = 0; k < frags; k++)
3568fae3551SRodney W. Grimes 				setbmap(i + j + k);
3578fae3551SRodney W. Grimes 			n_blks += frags;
3588fae3551SRodney W. Grimes 			return (i + j);
3598fae3551SRodney W. Grimes 		}
3608fae3551SRodney W. Grimes 	}
3618fae3551SRodney W. Grimes 	return (0);
3628fae3551SRodney W. Grimes }
3638fae3551SRodney W. Grimes 
3648fae3551SRodney W. Grimes /*
3658fae3551SRodney W. Grimes  * Free a previously allocated block
3668fae3551SRodney W. Grimes  */
3678fae3551SRodney W. Grimes freeblk(blkno, frags)
3688fae3551SRodney W. Grimes 	daddr_t blkno;
3698fae3551SRodney W. Grimes 	long frags;
3708fae3551SRodney W. Grimes {
3718fae3551SRodney W. Grimes 	struct inodesc idesc;
3728fae3551SRodney W. Grimes 
3738fae3551SRodney W. Grimes 	idesc.id_blkno = blkno;
3748fae3551SRodney W. Grimes 	idesc.id_numfrags = frags;
3758fae3551SRodney W. Grimes 	(void)pass4check(&idesc);
3768fae3551SRodney W. Grimes }
3778fae3551SRodney W. Grimes 
3788fae3551SRodney W. Grimes /*
3798fae3551SRodney W. Grimes  * Find a pathname
3808fae3551SRodney W. Grimes  */
3818fae3551SRodney W. Grimes getpathname(namebuf, curdir, ino)
3828fae3551SRodney W. Grimes 	char *namebuf;
3838fae3551SRodney W. Grimes 	ino_t curdir, ino;
3848fae3551SRodney W. Grimes {
3858fae3551SRodney W. Grimes 	int len;
3868fae3551SRodney W. Grimes 	register char *cp;
3878fae3551SRodney W. Grimes 	struct inodesc idesc;
3888fae3551SRodney W. Grimes 	static int busy = 0;
3898fae3551SRodney W. Grimes 	extern int findname();
3908fae3551SRodney W. Grimes 
3918fae3551SRodney W. Grimes 	if (curdir == ino && ino == ROOTINO) {
3928fae3551SRodney W. Grimes 		(void)strcpy(namebuf, "/");
3938fae3551SRodney W. Grimes 		return;
3948fae3551SRodney W. Grimes 	}
3958fae3551SRodney W. Grimes 	if (busy ||
3968fae3551SRodney W. Grimes 	    (statemap[curdir] != DSTATE && statemap[curdir] != DFOUND)) {
3978fae3551SRodney W. Grimes 		(void)strcpy(namebuf, "?");
3988fae3551SRodney W. Grimes 		return;
3998fae3551SRodney W. Grimes 	}
4008fae3551SRodney W. Grimes 	busy = 1;
4018fae3551SRodney W. Grimes 	bzero((char *)&idesc, sizeof(struct inodesc));
4028fae3551SRodney W. Grimes 	idesc.id_type = DATA;
4038fae3551SRodney W. Grimes 	idesc.id_fix = IGNORE;
4048fae3551SRodney W. Grimes 	cp = &namebuf[MAXPATHLEN - 1];
4058fae3551SRodney W. Grimes 	*cp = '\0';
4068fae3551SRodney W. Grimes 	if (curdir != ino) {
4078fae3551SRodney W. Grimes 		idesc.id_parent = curdir;
4088fae3551SRodney W. Grimes 		goto namelookup;
4098fae3551SRodney W. Grimes 	}
4108fae3551SRodney W. Grimes 	while (ino != ROOTINO) {
4118fae3551SRodney W. Grimes 		idesc.id_number = ino;
4128fae3551SRodney W. Grimes 		idesc.id_func = findino;
4138fae3551SRodney W. Grimes 		idesc.id_name = "..";
4148fae3551SRodney W. Grimes 		if ((ckinode(ginode(ino), &idesc) & FOUND) == 0)
4158fae3551SRodney W. Grimes 			break;
4168fae3551SRodney W. Grimes 	namelookup:
4178fae3551SRodney W. Grimes 		idesc.id_number = idesc.id_parent;
4188fae3551SRodney W. Grimes 		idesc.id_parent = ino;
4198fae3551SRodney W. Grimes 		idesc.id_func = findname;
4208fae3551SRodney W. Grimes 		idesc.id_name = namebuf;
4218fae3551SRodney W. Grimes 		if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0)
4228fae3551SRodney W. Grimes 			break;
4238fae3551SRodney W. Grimes 		len = strlen(namebuf);
4248fae3551SRodney W. Grimes 		cp -= len;
4258fae3551SRodney W. Grimes 		bcopy(namebuf, cp, (size_t)len);
4268fae3551SRodney W. Grimes 		*--cp = '/';
4278fae3551SRodney W. Grimes 		if (cp < &namebuf[MAXNAMLEN])
4288fae3551SRodney W. Grimes 			break;
4298fae3551SRodney W. Grimes 		ino = idesc.id_number;
4308fae3551SRodney W. Grimes 	}
4318fae3551SRodney W. Grimes 	busy = 0;
4328fae3551SRodney W. Grimes 	if (ino != ROOTINO)
4338fae3551SRodney W. Grimes 		*--cp = '?';
4348fae3551SRodney W. Grimes 	bcopy(cp, namebuf, (size_t)(&namebuf[MAXPATHLEN] - cp));
4358fae3551SRodney W. Grimes }
4368fae3551SRodney W. Grimes 
4378fae3551SRodney W. Grimes void
4388fae3551SRodney W. Grimes catch()
4398fae3551SRodney W. Grimes {
4408fae3551SRodney W. Grimes 	if (!doinglevel2)
4418fae3551SRodney W. Grimes 		ckfini();
4428fae3551SRodney W. Grimes 	exit(12);
4438fae3551SRodney W. Grimes }
4448fae3551SRodney W. Grimes 
4458fae3551SRodney W. Grimes /*
4468fae3551SRodney W. Grimes  * When preening, allow a single quit to signal
4478fae3551SRodney W. Grimes  * a special exit after filesystem checks complete
4488fae3551SRodney W. Grimes  * so that reboot sequence may be interrupted.
4498fae3551SRodney W. Grimes  */
4508fae3551SRodney W. Grimes void
4518fae3551SRodney W. Grimes catchquit()
4528fae3551SRodney W. Grimes {
4538fae3551SRodney W. Grimes 	extern returntosingle;
4548fae3551SRodney W. Grimes 
4558fae3551SRodney W. Grimes 	printf("returning to single-user after filesystem check\n");
4568fae3551SRodney W. Grimes 	returntosingle = 1;
4578fae3551SRodney W. Grimes 	(void)signal(SIGQUIT, SIG_DFL);
4588fae3551SRodney W. Grimes }
4598fae3551SRodney W. Grimes 
4608fae3551SRodney W. Grimes /*
4618fae3551SRodney W. Grimes  * Ignore a single quit signal; wait and flush just in case.
4628fae3551SRodney W. Grimes  * Used by child processes in preen.
4638fae3551SRodney W. Grimes  */
4648fae3551SRodney W. Grimes void
4658fae3551SRodney W. Grimes voidquit()
4668fae3551SRodney W. Grimes {
4678fae3551SRodney W. Grimes 
4688fae3551SRodney W. Grimes 	sleep(1);
4698fae3551SRodney W. Grimes 	(void)signal(SIGQUIT, SIG_IGN);
4708fae3551SRodney W. Grimes 	(void)signal(SIGQUIT, SIG_DFL);
4718fae3551SRodney W. Grimes }
4728fae3551SRodney W. Grimes 
4738fae3551SRodney W. Grimes /*
4748fae3551SRodney W. Grimes  * determine whether an inode should be fixed.
4758fae3551SRodney W. Grimes  */
4768fae3551SRodney W. Grimes dofix(idesc, msg)
4778fae3551SRodney W. Grimes 	register struct inodesc *idesc;
4788fae3551SRodney W. Grimes 	char *msg;
4798fae3551SRodney W. Grimes {
4808fae3551SRodney W. Grimes 
4818fae3551SRodney W. Grimes 	switch (idesc->id_fix) {
4828fae3551SRodney W. Grimes 
4838fae3551SRodney W. Grimes 	case DONTKNOW:
4848fae3551SRodney W. Grimes 		if (idesc->id_type == DATA)
4858fae3551SRodney W. Grimes 			direrror(idesc->id_number, msg);
4868fae3551SRodney W. Grimes 		else
4878fae3551SRodney W. Grimes 			pwarn(msg);
4888fae3551SRodney W. Grimes 		if (preen) {
4898fae3551SRodney W. Grimes 			printf(" (SALVAGED)\n");
4908fae3551SRodney W. Grimes 			idesc->id_fix = FIX;
4918fae3551SRodney W. Grimes 			return (ALTERED);
4928fae3551SRodney W. Grimes 		}
4938fae3551SRodney W. Grimes 		if (reply("SALVAGE") == 0) {
4948fae3551SRodney W. Grimes 			idesc->id_fix = NOFIX;
4958fae3551SRodney W. Grimes 			return (0);
4968fae3551SRodney W. Grimes 		}
4978fae3551SRodney W. Grimes 		idesc->id_fix = FIX;
4988fae3551SRodney W. Grimes 		return (ALTERED);
4998fae3551SRodney W. Grimes 
5008fae3551SRodney W. Grimes 	case FIX:
5018fae3551SRodney W. Grimes 		return (ALTERED);
5028fae3551SRodney W. Grimes 
5038fae3551SRodney W. Grimes 	case NOFIX:
5048fae3551SRodney W. Grimes 	case IGNORE:
5058fae3551SRodney W. Grimes 		return (0);
5068fae3551SRodney W. Grimes 
5078fae3551SRodney W. Grimes 	default:
5088fae3551SRodney W. Grimes 		errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix);
5098fae3551SRodney W. Grimes 	}
5108fae3551SRodney W. Grimes 	/* NOTREACHED */
5118fae3551SRodney W. Grimes }
5128fae3551SRodney W. Grimes 
5138fae3551SRodney W. Grimes /* VARARGS1 */
5148fae3551SRodney W. Grimes errexit(s1, s2, s3, s4)
5158fae3551SRodney W. Grimes 	char *s1;
5168fae3551SRodney W. Grimes {
5178fae3551SRodney W. Grimes 	printf(s1, s2, s3, s4);
5188fae3551SRodney W. Grimes 	exit(8);
5198fae3551SRodney W. Grimes }
5208fae3551SRodney W. Grimes 
5218fae3551SRodney W. Grimes /*
5228fae3551SRodney W. Grimes  * An unexpected inconsistency occured.
5238fae3551SRodney W. Grimes  * Die if preening, otherwise just print message and continue.
5248fae3551SRodney W. Grimes  */
5258fae3551SRodney W. Grimes /* VARARGS1 */
5268fae3551SRodney W. Grimes pfatal(s, a1, a2, a3)
5278fae3551SRodney W. Grimes 	char *s;
5288fae3551SRodney W. Grimes {
5298fae3551SRodney W. Grimes 
5308fae3551SRodney W. Grimes 	if (preen) {
5318fae3551SRodney W. Grimes 		printf("%s: ", cdevname);
5328fae3551SRodney W. Grimes 		printf(s, a1, a2, a3);
5338fae3551SRodney W. Grimes 		printf("\n");
5348fae3551SRodney W. Grimes 		printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
5358fae3551SRodney W. Grimes 			cdevname);
5368fae3551SRodney W. Grimes 		exit(8);
5378fae3551SRodney W. Grimes 	}
5388fae3551SRodney W. Grimes 	printf(s, a1, a2, a3);
5398fae3551SRodney W. Grimes }
5408fae3551SRodney W. Grimes 
5418fae3551SRodney W. Grimes /*
5428fae3551SRodney W. Grimes  * Pwarn just prints a message when not preening,
5438fae3551SRodney W. Grimes  * or a warning (preceded by filename) when preening.
5448fae3551SRodney W. Grimes  */
5458fae3551SRodney W. Grimes /* VARARGS1 */
5468fae3551SRodney W. Grimes pwarn(s, a1, a2, a3, a4, a5, a6)
5478fae3551SRodney W. Grimes 	char *s;
5488fae3551SRodney W. Grimes {
5498fae3551SRodney W. Grimes 
5508fae3551SRodney W. Grimes 	if (preen)
5518fae3551SRodney W. Grimes 		printf("%s: ", cdevname);
5528fae3551SRodney W. Grimes 	printf(s, a1, a2, a3, a4, a5, a6);
5538fae3551SRodney W. Grimes }
5548fae3551SRodney W. Grimes 
5558fae3551SRodney W. Grimes #ifndef lint
5568fae3551SRodney W. Grimes /*
5578fae3551SRodney W. Grimes  * Stub for routines from kernel.
5588fae3551SRodney W. Grimes  */
5598fae3551SRodney W. Grimes panic(s)
5608fae3551SRodney W. Grimes 	char *s;
5618fae3551SRodney W. Grimes {
5628fae3551SRodney W. Grimes 
5638fae3551SRodney W. Grimes 	pfatal("INTERNAL INCONSISTENCY:");
5648fae3551SRodney W. Grimes 	errexit(s);
5658fae3551SRodney W. Grimes }
5668fae3551SRodney W. Grimes #endif
567