utilities.c revision 34266
11558Srgrimes/* 21558Srgrimes * Copyright (c) 1980, 1986, 1993 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice, this list of conditions and the following disclaimer. 101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer in the 121558Srgrimes * documentation and/or other materials provided with the distribution. 131558Srgrimes * 3. All advertising materials mentioning features or use of this software 141558Srgrimes * must display the following acknowledgement: 151558Srgrimes * This product includes software developed by the University of 161558Srgrimes * California, Berkeley and its contributors. 171558Srgrimes * 4. Neither the name of the University nor the names of its contributors 181558Srgrimes * may be used to endorse or promote products derived from this software 191558Srgrimes * without specific prior written permission. 201558Srgrimes * 211558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311558Srgrimes * SUCH DAMAGE. 321558Srgrimes */ 331558Srgrimes 341558Srgrimes#ifndef lint 3523675Speterstatic const char sccsid[] = "@(#)utilities.c 8.6 (Berkeley) 5/19/95"; 361558Srgrimes#endif /* not lint */ 371558Srgrimes 381558Srgrimes#include <sys/param.h> 391558Srgrimes#include <sys/time.h> 4023675Speter 411558Srgrimes#include <ufs/ufs/dinode.h> 421558Srgrimes#include <ufs/ufs/dir.h> 431558Srgrimes#include <ufs/ffs/fs.h> 4423799Sbde 4523675Speter#include <ctype.h> 4623675Speter#include <err.h> 4723799Sbde#include <string.h> 4823675Speter 491558Srgrimes#include "fsck.h" 501558Srgrimes 511558Srgrimeslong diskreads, totalreads; /* Disk cache statistics */ 521558Srgrimes 5323675Speterstatic void rwerror __P((char *mesg, ufs_daddr_t blk)); 547585Sbde 557585Sbdeint 561558Srgrimesftypeok(dp) 571558Srgrimes struct dinode *dp; 581558Srgrimes{ 591558Srgrimes switch (dp->di_mode & IFMT) { 601558Srgrimes 611558Srgrimes case IFDIR: 621558Srgrimes case IFREG: 631558Srgrimes case IFBLK: 641558Srgrimes case IFCHR: 651558Srgrimes case IFLNK: 661558Srgrimes case IFSOCK: 671558Srgrimes case IFIFO: 681558Srgrimes return (1); 691558Srgrimes 701558Srgrimes default: 711558Srgrimes if (debug) 721558Srgrimes printf("bad file type 0%o\n", dp->di_mode); 731558Srgrimes return (0); 741558Srgrimes } 751558Srgrimes} 761558Srgrimes 777585Sbdeint 781558Srgrimesreply(question) 791558Srgrimes char *question; 801558Srgrimes{ 811558Srgrimes int persevere; 821558Srgrimes char c; 831558Srgrimes 841558Srgrimes if (preen) 851558Srgrimes pfatal("INTERNAL ERROR: GOT TO reply()"); 861558Srgrimes persevere = !strcmp(question, "CONTINUE"); 871558Srgrimes printf("\n"); 881558Srgrimes if (!persevere && (nflag || fswritefd < 0)) { 891558Srgrimes printf("%s? no\n\n", question); 9034266Sjulian resolved = 0; 911558Srgrimes return (0); 921558Srgrimes } 931558Srgrimes if (yflag || (persevere && nflag)) { 941558Srgrimes printf("%s? yes\n\n", question); 951558Srgrimes return (1); 961558Srgrimes } 971558Srgrimes do { 981558Srgrimes printf("%s? [yn] ", question); 991558Srgrimes (void) fflush(stdout); 1001558Srgrimes c = getc(stdin); 10134266Sjulian while (c != '\n' && getc(stdin) != '\n') { 10234266Sjulian if (feof(stdin)) { 10334266Sjulian resolved = 0; 1041558Srgrimes return (0); 10534266Sjulian } 10634266Sjulian } 1071558Srgrimes } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N'); 1081558Srgrimes printf("\n"); 1091558Srgrimes if (c == 'y' || c == 'Y') 1101558Srgrimes return (1); 11134266Sjulian resolved = 0; 1121558Srgrimes return (0); 1131558Srgrimes} 1141558Srgrimes 1151558Srgrimes/* 1161558Srgrimes * Malloc buffers and set up cache. 1171558Srgrimes */ 1187585Sbdevoid 1191558Srgrimesbufinit() 1201558Srgrimes{ 1211558Srgrimes register struct bufarea *bp; 1221558Srgrimes long bufcnt, i; 1231558Srgrimes char *bufp; 1241558Srgrimes 1251558Srgrimes pbp = pdirbp = (struct bufarea *)0; 1261558Srgrimes bufp = malloc((unsigned int)sblock.fs_bsize); 1271558Srgrimes if (bufp == 0) 12823675Speter errx(EEXIT, "cannot allocate buffer pool"); 1291558Srgrimes cgblk.b_un.b_buf = bufp; 1301558Srgrimes initbarea(&cgblk); 1311558Srgrimes bufhead.b_next = bufhead.b_prev = &bufhead; 1321558Srgrimes bufcnt = MAXBUFSPACE / sblock.fs_bsize; 1331558Srgrimes if (bufcnt < MINBUFS) 1341558Srgrimes bufcnt = MINBUFS; 1351558Srgrimes for (i = 0; i < bufcnt; i++) { 1361558Srgrimes bp = (struct bufarea *)malloc(sizeof(struct bufarea)); 1371558Srgrimes bufp = malloc((unsigned int)sblock.fs_bsize); 1381558Srgrimes if (bp == NULL || bufp == NULL) { 1391558Srgrimes if (i >= MINBUFS) 1401558Srgrimes break; 14123675Speter errx(EEXIT, "cannot allocate buffer pool"); 1421558Srgrimes } 1431558Srgrimes bp->b_un.b_buf = bufp; 1441558Srgrimes bp->b_prev = &bufhead; 1451558Srgrimes bp->b_next = bufhead.b_next; 1461558Srgrimes bufhead.b_next->b_prev = bp; 1471558Srgrimes bufhead.b_next = bp; 1481558Srgrimes initbarea(bp); 1491558Srgrimes } 1501558Srgrimes bufhead.b_size = i; /* save number of buffers */ 1511558Srgrimes} 1521558Srgrimes 1531558Srgrimes/* 1541558Srgrimes * Manage a cache of directory blocks. 1551558Srgrimes */ 1561558Srgrimesstruct bufarea * 1571558Srgrimesgetdatablk(blkno, size) 15823675Speter ufs_daddr_t blkno; 1591558Srgrimes long size; 1601558Srgrimes{ 1611558Srgrimes register struct bufarea *bp; 1621558Srgrimes 1631558Srgrimes for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next) 1641558Srgrimes if (bp->b_bno == fsbtodb(&sblock, blkno)) 1651558Srgrimes goto foundit; 1661558Srgrimes for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev) 1671558Srgrimes if ((bp->b_flags & B_INUSE) == 0) 1681558Srgrimes break; 1691558Srgrimes if (bp == &bufhead) 17023675Speter errx(EEXIT, "deadlocked buffer pool"); 1711558Srgrimes getblk(bp, blkno, size); 1721558Srgrimes /* fall through */ 1731558Srgrimesfoundit: 1741558Srgrimes totalreads++; 1751558Srgrimes bp->b_prev->b_next = bp->b_next; 1761558Srgrimes bp->b_next->b_prev = bp->b_prev; 1771558Srgrimes bp->b_prev = &bufhead; 1781558Srgrimes bp->b_next = bufhead.b_next; 1791558Srgrimes bufhead.b_next->b_prev = bp; 1801558Srgrimes bufhead.b_next = bp; 1811558Srgrimes bp->b_flags |= B_INUSE; 1821558Srgrimes return (bp); 1831558Srgrimes} 1841558Srgrimes 1851558Srgrimesvoid 1861558Srgrimesgetblk(bp, blk, size) 1871558Srgrimes register struct bufarea *bp; 18823675Speter ufs_daddr_t blk; 1891558Srgrimes long size; 1901558Srgrimes{ 19123675Speter ufs_daddr_t dblk; 1921558Srgrimes 1931558Srgrimes dblk = fsbtodb(&sblock, blk); 1941558Srgrimes if (bp->b_bno != dblk) { 1951558Srgrimes flush(fswritefd, bp); 1961558Srgrimes diskreads++; 1971558Srgrimes bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, dblk, size); 1981558Srgrimes bp->b_bno = dblk; 1991558Srgrimes bp->b_size = size; 2001558Srgrimes } 2011558Srgrimes} 2021558Srgrimes 2037585Sbdevoid 2041558Srgrimesflush(fd, bp) 2051558Srgrimes int fd; 2061558Srgrimes register struct bufarea *bp; 2071558Srgrimes{ 2081558Srgrimes register int i, j; 2091558Srgrimes 2101558Srgrimes if (!bp->b_dirty) 2111558Srgrimes return; 2121558Srgrimes if (bp->b_errs != 0) 2131558Srgrimes pfatal("WRITING %sZERO'ED BLOCK %d TO DISK\n", 2141558Srgrimes (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ", 2151558Srgrimes bp->b_bno); 2161558Srgrimes bp->b_dirty = 0; 2171558Srgrimes bp->b_errs = 0; 2181558Srgrimes bwrite(fd, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size); 2191558Srgrimes if (bp != &sblk) 2201558Srgrimes return; 2211558Srgrimes for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 2221558Srgrimes bwrite(fswritefd, (char *)sblock.fs_csp[j], 2231558Srgrimes fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), 2241558Srgrimes sblock.fs_cssize - i < sblock.fs_bsize ? 2251558Srgrimes sblock.fs_cssize - i : sblock.fs_bsize); 2261558Srgrimes } 2271558Srgrimes} 2281558Srgrimes 22923675Speterstatic void 2301558Srgrimesrwerror(mesg, blk) 2311558Srgrimes char *mesg; 23223675Speter ufs_daddr_t blk; 2331558Srgrimes{ 2341558Srgrimes 2351558Srgrimes if (preen == 0) 2361558Srgrimes printf("\n"); 2371558Srgrimes pfatal("CANNOT %s: BLK %ld", mesg, blk); 2381558Srgrimes if (reply("CONTINUE") == 0) 23923675Speter exit(EEXIT); 2401558Srgrimes} 2411558Srgrimes 2427585Sbdevoid 24323675Speterckfini(markclean) 24423675Speter int markclean; 2451558Srgrimes{ 2461558Srgrimes register struct bufarea *bp, *nbp; 24723675Speter int ofsmodified, cnt = 0; 2481558Srgrimes 2491558Srgrimes if (fswritefd < 0) { 2501558Srgrimes (void)close(fsreadfd); 2511558Srgrimes return; 2521558Srgrimes } 2531558Srgrimes flush(fswritefd, &sblk); 2541558Srgrimes if (havesb && sblk.b_bno != SBOFF / dev_bsize && 2551558Srgrimes !preen && reply("UPDATE STANDARD SUPERBLOCK")) { 2561558Srgrimes sblk.b_bno = SBOFF / dev_bsize; 2571558Srgrimes sbdirty(); 2581558Srgrimes flush(fswritefd, &sblk); 2591558Srgrimes } 2601558Srgrimes flush(fswritefd, &cgblk); 2611558Srgrimes free(cgblk.b_un.b_buf); 2621558Srgrimes for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) { 2631558Srgrimes cnt++; 2641558Srgrimes flush(fswritefd, bp); 2651558Srgrimes nbp = bp->b_prev; 2661558Srgrimes free(bp->b_un.b_buf); 2671558Srgrimes free((char *)bp); 2681558Srgrimes } 2691558Srgrimes if (bufhead.b_size != cnt) 27023675Speter errx(EEXIT, "Panic: lost %d buffers", bufhead.b_size - cnt); 2711558Srgrimes pbp = pdirbp = (struct bufarea *)0; 27223675Speter if (markclean && sblock.fs_clean == 0) { 27323675Speter sblock.fs_clean = 1; 27423675Speter sbdirty(); 27523675Speter ofsmodified = fsmodified; 27623675Speter flush(fswritefd, &sblk); 27723675Speter fsmodified = ofsmodified; 27823675Speter if (!preen) 27923675Speter printf("\n***** FILE SYSTEM MARKED CLEAN *****\n"); 28023675Speter } 2811558Srgrimes if (debug) 2821558Srgrimes printf("cache missed %ld of %ld (%d%%)\n", diskreads, 2831558Srgrimes totalreads, (int)(diskreads * 100 / totalreads)); 2841558Srgrimes (void)close(fsreadfd); 2851558Srgrimes (void)close(fswritefd); 2861558Srgrimes} 2871558Srgrimes 2887585Sbdeint 2891558Srgrimesbread(fd, buf, blk, size) 2901558Srgrimes int fd; 2911558Srgrimes char *buf; 29223675Speter ufs_daddr_t blk; 2931558Srgrimes long size; 2941558Srgrimes{ 2951558Srgrimes char *cp; 2961558Srgrimes int i, errs; 2971558Srgrimes off_t offset; 2981558Srgrimes 2991558Srgrimes offset = blk; 3001558Srgrimes offset *= dev_bsize; 3011558Srgrimes if (lseek(fd, offset, 0) < 0) 3021558Srgrimes rwerror("SEEK", blk); 3031558Srgrimes else if (read(fd, buf, (int)size) == size) 3041558Srgrimes return (0); 3051558Srgrimes rwerror("READ", blk); 3061558Srgrimes if (lseek(fd, offset, 0) < 0) 3071558Srgrimes rwerror("SEEK", blk); 3081558Srgrimes errs = 0; 30923675Speter memset(buf, 0, (size_t)size); 3101558Srgrimes printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:"); 3111558Srgrimes for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) { 3121558Srgrimes if (read(fd, cp, (int)secsize) != secsize) { 3131558Srgrimes (void)lseek(fd, offset + i + secsize, 0); 3141558Srgrimes if (secsize != dev_bsize && dev_bsize != 1) 3151558Srgrimes printf(" %ld (%ld),", 3161558Srgrimes (blk * dev_bsize + i) / secsize, 3171558Srgrimes blk + i / dev_bsize); 3181558Srgrimes else 3191558Srgrimes printf(" %ld,", blk + i / dev_bsize); 3201558Srgrimes errs++; 3211558Srgrimes } 3221558Srgrimes } 3231558Srgrimes printf("\n"); 3241558Srgrimes return (errs); 3251558Srgrimes} 3261558Srgrimes 3277585Sbdevoid 3281558Srgrimesbwrite(fd, buf, blk, size) 3291558Srgrimes int fd; 3301558Srgrimes char *buf; 33123675Speter ufs_daddr_t blk; 3321558Srgrimes long size; 3331558Srgrimes{ 3341558Srgrimes int i; 3351558Srgrimes char *cp; 3361558Srgrimes off_t offset; 3371558Srgrimes 3381558Srgrimes if (fd < 0) 3391558Srgrimes return; 3401558Srgrimes offset = blk; 3411558Srgrimes offset *= dev_bsize; 3421558Srgrimes if (lseek(fd, offset, 0) < 0) 3431558Srgrimes rwerror("SEEK", blk); 3441558Srgrimes else if (write(fd, buf, (int)size) == size) { 3451558Srgrimes fsmodified = 1; 3461558Srgrimes return; 3471558Srgrimes } 3481558Srgrimes rwerror("WRITE", blk); 3491558Srgrimes if (lseek(fd, offset, 0) < 0) 3501558Srgrimes rwerror("SEEK", blk); 3511558Srgrimes printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:"); 3521558Srgrimes for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize) 3531558Srgrimes if (write(fd, cp, (int)dev_bsize) != dev_bsize) { 3541558Srgrimes (void)lseek(fd, offset + i + dev_bsize, 0); 3551558Srgrimes printf(" %ld,", blk + i / dev_bsize); 3561558Srgrimes } 3571558Srgrimes printf("\n"); 3581558Srgrimes return; 3591558Srgrimes} 3601558Srgrimes 3611558Srgrimes/* 3621558Srgrimes * allocate a data block with the specified number of fragments 3631558Srgrimes */ 36423675Speterufs_daddr_t 3651558Srgrimesallocblk(frags) 3661558Srgrimes long frags; 3671558Srgrimes{ 36834266Sjulian int i, j, k, cg, baseblk; 36934266Sjulian struct cg *cgp = &cgrp; 3701558Srgrimes 3711558Srgrimes if (frags <= 0 || frags > sblock.fs_frag) 3721558Srgrimes return (0); 3731558Srgrimes for (i = 0; i < maxfsblock - sblock.fs_frag; i += sblock.fs_frag) { 3741558Srgrimes for (j = 0; j <= sblock.fs_frag - frags; j++) { 3751558Srgrimes if (testbmap(i + j)) 3761558Srgrimes continue; 3771558Srgrimes for (k = 1; k < frags; k++) 3781558Srgrimes if (testbmap(i + j + k)) 3791558Srgrimes break; 3801558Srgrimes if (k < frags) { 3811558Srgrimes j += k; 3821558Srgrimes continue; 3831558Srgrimes } 38434266Sjulian cg = dtog(&sblock, i + j); 38534266Sjulian getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize); 38634266Sjulian if (!cg_chkmagic(cgp)) 38734266Sjulian pfatal("CG %d: BAD MAGIC NUMBER\n", cg); 38834266Sjulian baseblk = dtogd(&sblock, i + j); 38934266Sjulian for (k = 0; k < frags; k++) { 3901558Srgrimes setbmap(i + j + k); 39134266Sjulian clrbit(cg_blksfree(cgp), baseblk + k); 39234266Sjulian } 3931558Srgrimes n_blks += frags; 39434266Sjulian if (frags == sblock.fs_frag) 39534266Sjulian cgp->cg_cs.cs_nbfree--; 39634266Sjulian else 39734266Sjulian cgp->cg_cs.cs_nffree -= frags; 39834266Sjulian cgdirty(); 3991558Srgrimes return (i + j); 4001558Srgrimes } 4011558Srgrimes } 4021558Srgrimes return (0); 4031558Srgrimes} 4041558Srgrimes 4051558Srgrimes/* 4061558Srgrimes * Free a previously allocated block 4071558Srgrimes */ 4087585Sbdevoid 4091558Srgrimesfreeblk(blkno, frags) 41023675Speter ufs_daddr_t blkno; 4111558Srgrimes long frags; 4121558Srgrimes{ 4131558Srgrimes struct inodesc idesc; 4141558Srgrimes 4151558Srgrimes idesc.id_blkno = blkno; 4161558Srgrimes idesc.id_numfrags = frags; 4171558Srgrimes (void)pass4check(&idesc); 4181558Srgrimes} 4191558Srgrimes 4201558Srgrimes/* 4211558Srgrimes * Find a pathname 4221558Srgrimes */ 4237585Sbdevoid 4241558Srgrimesgetpathname(namebuf, curdir, ino) 4251558Srgrimes char *namebuf; 4261558Srgrimes ino_t curdir, ino; 4271558Srgrimes{ 4281558Srgrimes int len; 4291558Srgrimes register char *cp; 4301558Srgrimes struct inodesc idesc; 4311558Srgrimes static int busy = 0; 4321558Srgrimes 4331558Srgrimes if (curdir == ino && ino == ROOTINO) { 4341558Srgrimes (void)strcpy(namebuf, "/"); 4351558Srgrimes return; 4361558Srgrimes } 4371558Srgrimes if (busy || 4381558Srgrimes (statemap[curdir] != DSTATE && statemap[curdir] != DFOUND)) { 4391558Srgrimes (void)strcpy(namebuf, "?"); 4401558Srgrimes return; 4411558Srgrimes } 4421558Srgrimes busy = 1; 44323675Speter memset(&idesc, 0, sizeof(struct inodesc)); 4441558Srgrimes idesc.id_type = DATA; 4451558Srgrimes idesc.id_fix = IGNORE; 4461558Srgrimes cp = &namebuf[MAXPATHLEN - 1]; 4471558Srgrimes *cp = '\0'; 4481558Srgrimes if (curdir != ino) { 4491558Srgrimes idesc.id_parent = curdir; 4501558Srgrimes goto namelookup; 4511558Srgrimes } 4521558Srgrimes while (ino != ROOTINO) { 4531558Srgrimes idesc.id_number = ino; 4541558Srgrimes idesc.id_func = findino; 4551558Srgrimes idesc.id_name = ".."; 4561558Srgrimes if ((ckinode(ginode(ino), &idesc) & FOUND) == 0) 4571558Srgrimes break; 4581558Srgrimes namelookup: 4591558Srgrimes idesc.id_number = idesc.id_parent; 4601558Srgrimes idesc.id_parent = ino; 4611558Srgrimes idesc.id_func = findname; 4621558Srgrimes idesc.id_name = namebuf; 4631558Srgrimes if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0) 4641558Srgrimes break; 4651558Srgrimes len = strlen(namebuf); 4661558Srgrimes cp -= len; 46723675Speter memmove(cp, namebuf, (size_t)len); 4681558Srgrimes *--cp = '/'; 4691558Srgrimes if (cp < &namebuf[MAXNAMLEN]) 4701558Srgrimes break; 4711558Srgrimes ino = idesc.id_number; 4721558Srgrimes } 4731558Srgrimes busy = 0; 4741558Srgrimes if (ino != ROOTINO) 4751558Srgrimes *--cp = '?'; 47623675Speter memmove(namebuf, cp, (size_t)(&namebuf[MAXPATHLEN] - cp)); 4771558Srgrimes} 4781558Srgrimes 4791558Srgrimesvoid 48023675Spetercatch(sig) 48123675Speter int sig; 4821558Srgrimes{ 4831558Srgrimes if (!doinglevel2) 48423675Speter ckfini(0); 4851558Srgrimes exit(12); 4861558Srgrimes} 4871558Srgrimes 4881558Srgrimes/* 4891558Srgrimes * When preening, allow a single quit to signal 4901558Srgrimes * a special exit after filesystem checks complete 4911558Srgrimes * so that reboot sequence may be interrupted. 4921558Srgrimes */ 4931558Srgrimesvoid 49423675Spetercatchquit(sig) 49523675Speter int sig; 4961558Srgrimes{ 4971558Srgrimes printf("returning to single-user after filesystem check\n"); 4981558Srgrimes returntosingle = 1; 4991558Srgrimes (void)signal(SIGQUIT, SIG_DFL); 5001558Srgrimes} 5011558Srgrimes 5021558Srgrimes/* 5031558Srgrimes * Ignore a single quit signal; wait and flush just in case. 5041558Srgrimes * Used by child processes in preen. 5051558Srgrimes */ 5061558Srgrimesvoid 50723675Spetervoidquit(sig) 50823675Speter int sig; 5091558Srgrimes{ 5101558Srgrimes 5111558Srgrimes sleep(1); 5121558Srgrimes (void)signal(SIGQUIT, SIG_IGN); 5131558Srgrimes (void)signal(SIGQUIT, SIG_DFL); 5141558Srgrimes} 5151558Srgrimes 5161558Srgrimes/* 5171558Srgrimes * determine whether an inode should be fixed. 5181558Srgrimes */ 5197585Sbdeint 5201558Srgrimesdofix(idesc, msg) 5211558Srgrimes register struct inodesc *idesc; 5221558Srgrimes char *msg; 5231558Srgrimes{ 5241558Srgrimes 5251558Srgrimes switch (idesc->id_fix) { 5261558Srgrimes 5271558Srgrimes case DONTKNOW: 5281558Srgrimes if (idesc->id_type == DATA) 5291558Srgrimes direrror(idesc->id_number, msg); 5301558Srgrimes else 5311558Srgrimes pwarn(msg); 5321558Srgrimes if (preen) { 5331558Srgrimes printf(" (SALVAGED)\n"); 5341558Srgrimes idesc->id_fix = FIX; 5351558Srgrimes return (ALTERED); 5361558Srgrimes } 5371558Srgrimes if (reply("SALVAGE") == 0) { 5381558Srgrimes idesc->id_fix = NOFIX; 5391558Srgrimes return (0); 5401558Srgrimes } 5411558Srgrimes idesc->id_fix = FIX; 5421558Srgrimes return (ALTERED); 5431558Srgrimes 5441558Srgrimes case FIX: 5451558Srgrimes return (ALTERED); 5461558Srgrimes 5471558Srgrimes case NOFIX: 5481558Srgrimes case IGNORE: 5491558Srgrimes return (0); 5501558Srgrimes 5511558Srgrimes default: 55223675Speter errx(EEXIT, "UNKNOWN INODESC FIX MODE %d", idesc->id_fix); 5531558Srgrimes } 5541558Srgrimes /* NOTREACHED */ 55523675Speter return (0); 5561558Srgrimes} 5571558Srgrimes 55823675Speter#if __STDC__ 55923675Speter#include <stdarg.h> 56023675Speter#else 56123675Speter#include <varargs.h> 56223675Speter#endif 5631558Srgrimes 5641558Srgrimes/* 5651558Srgrimes * An unexpected inconsistency occured. 56634266Sjulian * Die if preening or filesystem is running with soft dependency protocol, 56734266Sjulian * otherwise just print message and continue. 5681558Srgrimes */ 5697585Sbdevoid 57023675Speter#if __STDC__ 57123675Speterpfatal(const char *fmt, ...) 57223675Speter#else 57323675Speterpfatal(fmt, va_alist) 57423675Speter char *fmt; 57523675Speter va_dcl 57623675Speter#endif 5771558Srgrimes{ 5787585Sbde va_list ap; 57923675Speter#if __STDC__ 58023675Speter va_start(ap, fmt); 58123675Speter#else 58223675Speter va_start(ap); 58323675Speter#endif 58423675Speter if (!preen) { 58523675Speter (void)vfprintf(stderr, fmt, ap); 58623675Speter va_end(ap); 58734266Sjulian if (usedsoftdep) 58834266Sjulian (void)fprintf(stderr, 58934266Sjulian "\nUNEXPECTED SOFTDEP INCONSISTENCY\n"); 59023675Speter return; 5911558Srgrimes } 59223675Speter (void)fprintf(stderr, "%s: ", cdevname); 59323675Speter (void)vfprintf(stderr, fmt, ap); 59423675Speter (void)fprintf(stderr, 59534266Sjulian "\n%s: UNEXPECTED%sINCONSISTENCY; RUN fsck MANUALLY.\n", 59634266Sjulian cdevname, usedsoftdep ? " SOFTDEP " : " "); 59734266Sjulian ckfini(0); 59823675Speter exit(EEXIT); 5991558Srgrimes} 6001558Srgrimes 6011558Srgrimes/* 60234266Sjulian * Pwarn just prints a message when not preening or running soft dependency 60334266Sjulian * protocol, or a warning (preceded by filename) when preening. 6041558Srgrimes */ 6057585Sbdevoid 60623675Speter#if __STDC__ 60723675Speterpwarn(const char *fmt, ...) 60823675Speter#else 60923675Speterpwarn(fmt, va_alist) 61023675Speter char *fmt; 61123675Speter va_dcl 61223675Speter#endif 6131558Srgrimes{ 6147585Sbde va_list ap; 61523675Speter#if __STDC__ 61623675Speter va_start(ap, fmt); 61723675Speter#else 61823675Speter va_start(ap); 61923675Speter#endif 6201558Srgrimes if (preen) 62123675Speter (void)fprintf(stderr, "%s: ", cdevname); 62223675Speter (void)vfprintf(stderr, fmt, ap); 6237585Sbde va_end(ap); 6241558Srgrimes} 6251558Srgrimes 6261558Srgrimes/* 6271558Srgrimes * Stub for routines from kernel. 6281558Srgrimes */ 62918286Sbdevoid 63023675Speter#if __STDC__ 6317585Sbdepanic(const char *fmt, ...) 6327585Sbde#else 6337585Sbdepanic(fmt, va_alist) 6347585Sbde char *fmt; 63523675Speter va_dcl 6367585Sbde#endif 6371558Srgrimes{ 63823675Speter va_list ap; 63923675Speter#if __STDC__ 64023675Speter va_start(ap, fmt); 64123675Speter#else 64223675Speter va_start(ap); 64323675Speter#endif 6441558Srgrimes pfatal("INTERNAL INCONSISTENCY:"); 64523675Speter (void)vfprintf(stderr, fmt, ap); 64623675Speter va_end(ap); 64723675Speter exit(EEXIT); 6481558Srgrimes} 649