utilities.c revision 23675
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> 441558Srgrimes#include <stdio.h> 451558Srgrimes#include <stdlib.h> 467585Sbde#include <unistd.h> 477585Sbde#include <stdarg.h> 481558Srgrimes#include <string.h> 4923675Speter#include <ctype.h> 5023675Speter#include <err.h> 5123675Speter 521558Srgrimes#include "fsck.h" 531558Srgrimes 541558Srgrimeslong diskreads, totalreads; /* Disk cache statistics */ 551558Srgrimes 5623675Speterstatic void rwerror __P((char *mesg, ufs_daddr_t blk)); 577585Sbde 587585Sbdeint 591558Srgrimesftypeok(dp) 601558Srgrimes struct dinode *dp; 611558Srgrimes{ 621558Srgrimes switch (dp->di_mode & IFMT) { 631558Srgrimes 641558Srgrimes case IFDIR: 651558Srgrimes case IFREG: 661558Srgrimes case IFBLK: 671558Srgrimes case IFCHR: 681558Srgrimes case IFLNK: 691558Srgrimes case IFSOCK: 701558Srgrimes case IFIFO: 711558Srgrimes return (1); 721558Srgrimes 731558Srgrimes default: 741558Srgrimes if (debug) 751558Srgrimes printf("bad file type 0%o\n", dp->di_mode); 761558Srgrimes return (0); 771558Srgrimes } 781558Srgrimes} 791558Srgrimes 807585Sbdeint 811558Srgrimesreply(question) 821558Srgrimes char *question; 831558Srgrimes{ 841558Srgrimes int persevere; 851558Srgrimes char c; 861558Srgrimes 871558Srgrimes if (preen) 881558Srgrimes pfatal("INTERNAL ERROR: GOT TO reply()"); 891558Srgrimes persevere = !strcmp(question, "CONTINUE"); 901558Srgrimes printf("\n"); 911558Srgrimes if (!persevere && (nflag || fswritefd < 0)) { 921558Srgrimes printf("%s? no\n\n", question); 931558Srgrimes return (0); 941558Srgrimes } 951558Srgrimes if (yflag || (persevere && nflag)) { 961558Srgrimes printf("%s? yes\n\n", question); 971558Srgrimes return (1); 981558Srgrimes } 991558Srgrimes do { 1001558Srgrimes printf("%s? [yn] ", question); 1011558Srgrimes (void) fflush(stdout); 1021558Srgrimes c = getc(stdin); 1031558Srgrimes while (c != '\n' && getc(stdin) != '\n') 1041558Srgrimes if (feof(stdin)) 1051558Srgrimes return (0); 1061558Srgrimes } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N'); 1071558Srgrimes printf("\n"); 1081558Srgrimes if (c == 'y' || c == 'Y') 1091558Srgrimes return (1); 1101558Srgrimes return (0); 1111558Srgrimes} 1121558Srgrimes 1131558Srgrimes/* 1141558Srgrimes * Malloc buffers and set up cache. 1151558Srgrimes */ 1167585Sbdevoid 1171558Srgrimesbufinit() 1181558Srgrimes{ 1191558Srgrimes register struct bufarea *bp; 1201558Srgrimes long bufcnt, i; 1211558Srgrimes char *bufp; 1221558Srgrimes 1231558Srgrimes pbp = pdirbp = (struct bufarea *)0; 1241558Srgrimes bufp = malloc((unsigned int)sblock.fs_bsize); 1251558Srgrimes if (bufp == 0) 12623675Speter errx(EEXIT, "cannot allocate buffer pool"); 1271558Srgrimes cgblk.b_un.b_buf = bufp; 1281558Srgrimes initbarea(&cgblk); 1291558Srgrimes bufhead.b_next = bufhead.b_prev = &bufhead; 1301558Srgrimes bufcnt = MAXBUFSPACE / sblock.fs_bsize; 1311558Srgrimes if (bufcnt < MINBUFS) 1321558Srgrimes bufcnt = MINBUFS; 1331558Srgrimes for (i = 0; i < bufcnt; i++) { 1341558Srgrimes bp = (struct bufarea *)malloc(sizeof(struct bufarea)); 1351558Srgrimes bufp = malloc((unsigned int)sblock.fs_bsize); 1361558Srgrimes if (bp == NULL || bufp == NULL) { 1371558Srgrimes if (i >= MINBUFS) 1381558Srgrimes break; 13923675Speter errx(EEXIT, "cannot allocate buffer pool"); 1401558Srgrimes } 1411558Srgrimes bp->b_un.b_buf = bufp; 1421558Srgrimes bp->b_prev = &bufhead; 1431558Srgrimes bp->b_next = bufhead.b_next; 1441558Srgrimes bufhead.b_next->b_prev = bp; 1451558Srgrimes bufhead.b_next = bp; 1461558Srgrimes initbarea(bp); 1471558Srgrimes } 1481558Srgrimes bufhead.b_size = i; /* save number of buffers */ 1491558Srgrimes} 1501558Srgrimes 1511558Srgrimes/* 1521558Srgrimes * Manage a cache of directory blocks. 1531558Srgrimes */ 1541558Srgrimesstruct bufarea * 1551558Srgrimesgetdatablk(blkno, size) 15623675Speter ufs_daddr_t blkno; 1571558Srgrimes long size; 1581558Srgrimes{ 1591558Srgrimes register struct bufarea *bp; 1601558Srgrimes 1611558Srgrimes for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next) 1621558Srgrimes if (bp->b_bno == fsbtodb(&sblock, blkno)) 1631558Srgrimes goto foundit; 1641558Srgrimes for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev) 1651558Srgrimes if ((bp->b_flags & B_INUSE) == 0) 1661558Srgrimes break; 1671558Srgrimes if (bp == &bufhead) 16823675Speter errx(EEXIT, "deadlocked buffer pool"); 1691558Srgrimes getblk(bp, blkno, size); 1701558Srgrimes /* fall through */ 1711558Srgrimesfoundit: 1721558Srgrimes totalreads++; 1731558Srgrimes bp->b_prev->b_next = bp->b_next; 1741558Srgrimes bp->b_next->b_prev = bp->b_prev; 1751558Srgrimes bp->b_prev = &bufhead; 1761558Srgrimes bp->b_next = bufhead.b_next; 1771558Srgrimes bufhead.b_next->b_prev = bp; 1781558Srgrimes bufhead.b_next = bp; 1791558Srgrimes bp->b_flags |= B_INUSE; 1801558Srgrimes return (bp); 1811558Srgrimes} 1821558Srgrimes 1831558Srgrimesvoid 1841558Srgrimesgetblk(bp, blk, size) 1851558Srgrimes register struct bufarea *bp; 18623675Speter ufs_daddr_t blk; 1871558Srgrimes long size; 1881558Srgrimes{ 18923675Speter ufs_daddr_t dblk; 1901558Srgrimes 1911558Srgrimes dblk = fsbtodb(&sblock, blk); 1921558Srgrimes if (bp->b_bno != dblk) { 1931558Srgrimes flush(fswritefd, bp); 1941558Srgrimes diskreads++; 1951558Srgrimes bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, dblk, size); 1961558Srgrimes bp->b_bno = dblk; 1971558Srgrimes bp->b_size = size; 1981558Srgrimes } 1991558Srgrimes} 2001558Srgrimes 2017585Sbdevoid 2021558Srgrimesflush(fd, bp) 2031558Srgrimes int fd; 2041558Srgrimes register struct bufarea *bp; 2051558Srgrimes{ 2061558Srgrimes register int i, j; 2071558Srgrimes 2081558Srgrimes if (!bp->b_dirty) 2091558Srgrimes return; 2101558Srgrimes if (bp->b_errs != 0) 2111558Srgrimes pfatal("WRITING %sZERO'ED BLOCK %d TO DISK\n", 2121558Srgrimes (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ", 2131558Srgrimes bp->b_bno); 2141558Srgrimes bp->b_dirty = 0; 2151558Srgrimes bp->b_errs = 0; 2161558Srgrimes bwrite(fd, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size); 2171558Srgrimes if (bp != &sblk) 2181558Srgrimes return; 2191558Srgrimes for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 2201558Srgrimes bwrite(fswritefd, (char *)sblock.fs_csp[j], 2211558Srgrimes fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), 2221558Srgrimes sblock.fs_cssize - i < sblock.fs_bsize ? 2231558Srgrimes sblock.fs_cssize - i : sblock.fs_bsize); 2241558Srgrimes } 2251558Srgrimes} 2261558Srgrimes 22723675Speterstatic void 2281558Srgrimesrwerror(mesg, blk) 2291558Srgrimes char *mesg; 23023675Speter ufs_daddr_t blk; 2311558Srgrimes{ 2321558Srgrimes 2331558Srgrimes if (preen == 0) 2341558Srgrimes printf("\n"); 2351558Srgrimes pfatal("CANNOT %s: BLK %ld", mesg, blk); 2361558Srgrimes if (reply("CONTINUE") == 0) 23723675Speter exit(EEXIT); 2381558Srgrimes} 2391558Srgrimes 2407585Sbdevoid 24123675Speterckfini(markclean) 24223675Speter int markclean; 2431558Srgrimes{ 2441558Srgrimes register struct bufarea *bp, *nbp; 24523675Speter int ofsmodified, cnt = 0; 2461558Srgrimes 2471558Srgrimes if (fswritefd < 0) { 2481558Srgrimes (void)close(fsreadfd); 2491558Srgrimes return; 2501558Srgrimes } 2511558Srgrimes flush(fswritefd, &sblk); 2521558Srgrimes if (havesb && sblk.b_bno != SBOFF / dev_bsize && 2531558Srgrimes !preen && reply("UPDATE STANDARD SUPERBLOCK")) { 2541558Srgrimes sblk.b_bno = SBOFF / dev_bsize; 2551558Srgrimes sbdirty(); 2561558Srgrimes flush(fswritefd, &sblk); 2571558Srgrimes } 2581558Srgrimes flush(fswritefd, &cgblk); 2591558Srgrimes free(cgblk.b_un.b_buf); 2601558Srgrimes for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) { 2611558Srgrimes cnt++; 2621558Srgrimes flush(fswritefd, bp); 2631558Srgrimes nbp = bp->b_prev; 2641558Srgrimes free(bp->b_un.b_buf); 2651558Srgrimes free((char *)bp); 2661558Srgrimes } 2671558Srgrimes if (bufhead.b_size != cnt) 26823675Speter errx(EEXIT, "Panic: lost %d buffers", bufhead.b_size - cnt); 2691558Srgrimes pbp = pdirbp = (struct bufarea *)0; 27023675Speter if (markclean && sblock.fs_clean == 0) { 27123675Speter sblock.fs_clean = 1; 27223675Speter sbdirty(); 27323675Speter ofsmodified = fsmodified; 27423675Speter flush(fswritefd, &sblk); 27523675Speter fsmodified = ofsmodified; 27623675Speter if (!preen) 27723675Speter printf("\n***** FILE SYSTEM MARKED CLEAN *****\n"); 27823675Speter } 2791558Srgrimes if (debug) 2801558Srgrimes printf("cache missed %ld of %ld (%d%%)\n", diskreads, 2811558Srgrimes totalreads, (int)(diskreads * 100 / totalreads)); 2821558Srgrimes (void)close(fsreadfd); 2831558Srgrimes (void)close(fswritefd); 2841558Srgrimes} 2851558Srgrimes 2867585Sbdeint 2871558Srgrimesbread(fd, buf, blk, size) 2881558Srgrimes int fd; 2891558Srgrimes char *buf; 29023675Speter ufs_daddr_t blk; 2911558Srgrimes long size; 2921558Srgrimes{ 2931558Srgrimes char *cp; 2941558Srgrimes int i, errs; 2951558Srgrimes off_t offset; 2961558Srgrimes 2971558Srgrimes offset = blk; 2981558Srgrimes offset *= dev_bsize; 2991558Srgrimes if (lseek(fd, offset, 0) < 0) 3001558Srgrimes rwerror("SEEK", blk); 3011558Srgrimes else if (read(fd, buf, (int)size) == size) 3021558Srgrimes return (0); 3031558Srgrimes rwerror("READ", blk); 3041558Srgrimes if (lseek(fd, offset, 0) < 0) 3051558Srgrimes rwerror("SEEK", blk); 3061558Srgrimes errs = 0; 30723675Speter memset(buf, 0, (size_t)size); 3081558Srgrimes printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:"); 3091558Srgrimes for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) { 3101558Srgrimes if (read(fd, cp, (int)secsize) != secsize) { 3111558Srgrimes (void)lseek(fd, offset + i + secsize, 0); 3121558Srgrimes if (secsize != dev_bsize && dev_bsize != 1) 3131558Srgrimes printf(" %ld (%ld),", 3141558Srgrimes (blk * dev_bsize + i) / secsize, 3151558Srgrimes blk + i / dev_bsize); 3161558Srgrimes else 3171558Srgrimes printf(" %ld,", blk + i / dev_bsize); 3181558Srgrimes errs++; 3191558Srgrimes } 3201558Srgrimes } 3211558Srgrimes printf("\n"); 3221558Srgrimes return (errs); 3231558Srgrimes} 3241558Srgrimes 3257585Sbdevoid 3261558Srgrimesbwrite(fd, buf, blk, size) 3271558Srgrimes int fd; 3281558Srgrimes char *buf; 32923675Speter ufs_daddr_t blk; 3301558Srgrimes long size; 3311558Srgrimes{ 3321558Srgrimes int i; 3331558Srgrimes char *cp; 3341558Srgrimes off_t offset; 3351558Srgrimes 3361558Srgrimes if (fd < 0) 3371558Srgrimes return; 3381558Srgrimes offset = blk; 3391558Srgrimes offset *= dev_bsize; 3401558Srgrimes if (lseek(fd, offset, 0) < 0) 3411558Srgrimes rwerror("SEEK", blk); 3421558Srgrimes else if (write(fd, buf, (int)size) == size) { 3431558Srgrimes fsmodified = 1; 3441558Srgrimes return; 3451558Srgrimes } 3461558Srgrimes rwerror("WRITE", blk); 3471558Srgrimes if (lseek(fd, offset, 0) < 0) 3481558Srgrimes rwerror("SEEK", blk); 3491558Srgrimes printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:"); 3501558Srgrimes for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize) 3511558Srgrimes if (write(fd, cp, (int)dev_bsize) != dev_bsize) { 3521558Srgrimes (void)lseek(fd, offset + i + dev_bsize, 0); 3531558Srgrimes printf(" %ld,", blk + i / dev_bsize); 3541558Srgrimes } 3551558Srgrimes printf("\n"); 3561558Srgrimes return; 3571558Srgrimes} 3581558Srgrimes 3591558Srgrimes/* 3601558Srgrimes * allocate a data block with the specified number of fragments 3611558Srgrimes */ 36223675Speterufs_daddr_t 3631558Srgrimesallocblk(frags) 3641558Srgrimes long frags; 3651558Srgrimes{ 3661558Srgrimes register int i, j, k; 3671558Srgrimes 3681558Srgrimes if (frags <= 0 || frags > sblock.fs_frag) 3691558Srgrimes return (0); 3701558Srgrimes for (i = 0; i < maxfsblock - sblock.fs_frag; i += sblock.fs_frag) { 3711558Srgrimes for (j = 0; j <= sblock.fs_frag - frags; j++) { 3721558Srgrimes if (testbmap(i + j)) 3731558Srgrimes continue; 3741558Srgrimes for (k = 1; k < frags; k++) 3751558Srgrimes if (testbmap(i + j + k)) 3761558Srgrimes break; 3771558Srgrimes if (k < frags) { 3781558Srgrimes j += k; 3791558Srgrimes continue; 3801558Srgrimes } 3811558Srgrimes for (k = 0; k < frags; k++) 3821558Srgrimes setbmap(i + j + k); 3831558Srgrimes n_blks += frags; 3841558Srgrimes return (i + j); 3851558Srgrimes } 3861558Srgrimes } 3871558Srgrimes return (0); 3881558Srgrimes} 3891558Srgrimes 3901558Srgrimes/* 3911558Srgrimes * Free a previously allocated block 3921558Srgrimes */ 3937585Sbdevoid 3941558Srgrimesfreeblk(blkno, frags) 39523675Speter ufs_daddr_t blkno; 3961558Srgrimes long frags; 3971558Srgrimes{ 3981558Srgrimes struct inodesc idesc; 3991558Srgrimes 4001558Srgrimes idesc.id_blkno = blkno; 4011558Srgrimes idesc.id_numfrags = frags; 4021558Srgrimes (void)pass4check(&idesc); 4031558Srgrimes} 4041558Srgrimes 4051558Srgrimes/* 4061558Srgrimes * Find a pathname 4071558Srgrimes */ 4087585Sbdevoid 4091558Srgrimesgetpathname(namebuf, curdir, ino) 4101558Srgrimes char *namebuf; 4111558Srgrimes ino_t curdir, ino; 4121558Srgrimes{ 4131558Srgrimes int len; 4141558Srgrimes register char *cp; 4151558Srgrimes struct inodesc idesc; 4161558Srgrimes static int busy = 0; 4171558Srgrimes 4181558Srgrimes if (curdir == ino && ino == ROOTINO) { 4191558Srgrimes (void)strcpy(namebuf, "/"); 4201558Srgrimes return; 4211558Srgrimes } 4221558Srgrimes if (busy || 4231558Srgrimes (statemap[curdir] != DSTATE && statemap[curdir] != DFOUND)) { 4241558Srgrimes (void)strcpy(namebuf, "?"); 4251558Srgrimes return; 4261558Srgrimes } 4271558Srgrimes busy = 1; 42823675Speter memset(&idesc, 0, sizeof(struct inodesc)); 4291558Srgrimes idesc.id_type = DATA; 4301558Srgrimes idesc.id_fix = IGNORE; 4311558Srgrimes cp = &namebuf[MAXPATHLEN - 1]; 4321558Srgrimes *cp = '\0'; 4331558Srgrimes if (curdir != ino) { 4341558Srgrimes idesc.id_parent = curdir; 4351558Srgrimes goto namelookup; 4361558Srgrimes } 4371558Srgrimes while (ino != ROOTINO) { 4381558Srgrimes idesc.id_number = ino; 4391558Srgrimes idesc.id_func = findino; 4401558Srgrimes idesc.id_name = ".."; 4411558Srgrimes if ((ckinode(ginode(ino), &idesc) & FOUND) == 0) 4421558Srgrimes break; 4431558Srgrimes namelookup: 4441558Srgrimes idesc.id_number = idesc.id_parent; 4451558Srgrimes idesc.id_parent = ino; 4461558Srgrimes idesc.id_func = findname; 4471558Srgrimes idesc.id_name = namebuf; 4481558Srgrimes if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0) 4491558Srgrimes break; 4501558Srgrimes len = strlen(namebuf); 4511558Srgrimes cp -= len; 45223675Speter memmove(cp, namebuf, (size_t)len); 4531558Srgrimes *--cp = '/'; 4541558Srgrimes if (cp < &namebuf[MAXNAMLEN]) 4551558Srgrimes break; 4561558Srgrimes ino = idesc.id_number; 4571558Srgrimes } 4581558Srgrimes busy = 0; 4591558Srgrimes if (ino != ROOTINO) 4601558Srgrimes *--cp = '?'; 46123675Speter memmove(namebuf, cp, (size_t)(&namebuf[MAXPATHLEN] - cp)); 4621558Srgrimes} 4631558Srgrimes 4641558Srgrimesvoid 46523675Spetercatch(sig) 46623675Speter int sig; 4671558Srgrimes{ 4681558Srgrimes if (!doinglevel2) 46923675Speter ckfini(0); 4701558Srgrimes exit(12); 4711558Srgrimes} 4721558Srgrimes 4731558Srgrimes/* 4741558Srgrimes * When preening, allow a single quit to signal 4751558Srgrimes * a special exit after filesystem checks complete 4761558Srgrimes * so that reboot sequence may be interrupted. 4771558Srgrimes */ 4781558Srgrimesvoid 47923675Spetercatchquit(sig) 48023675Speter int sig; 4811558Srgrimes{ 4821558Srgrimes printf("returning to single-user after filesystem check\n"); 4831558Srgrimes returntosingle = 1; 4841558Srgrimes (void)signal(SIGQUIT, SIG_DFL); 4851558Srgrimes} 4861558Srgrimes 4871558Srgrimes/* 4881558Srgrimes * Ignore a single quit signal; wait and flush just in case. 4891558Srgrimes * Used by child processes in preen. 4901558Srgrimes */ 4911558Srgrimesvoid 49223675Spetervoidquit(sig) 49323675Speter int sig; 4941558Srgrimes{ 4951558Srgrimes 4961558Srgrimes sleep(1); 4971558Srgrimes (void)signal(SIGQUIT, SIG_IGN); 4981558Srgrimes (void)signal(SIGQUIT, SIG_DFL); 4991558Srgrimes} 5001558Srgrimes 5011558Srgrimes/* 5021558Srgrimes * determine whether an inode should be fixed. 5031558Srgrimes */ 5047585Sbdeint 5051558Srgrimesdofix(idesc, msg) 5061558Srgrimes register struct inodesc *idesc; 5071558Srgrimes char *msg; 5081558Srgrimes{ 5091558Srgrimes 5101558Srgrimes switch (idesc->id_fix) { 5111558Srgrimes 5121558Srgrimes case DONTKNOW: 5131558Srgrimes if (idesc->id_type == DATA) 5141558Srgrimes direrror(idesc->id_number, msg); 5151558Srgrimes else 5161558Srgrimes pwarn(msg); 5171558Srgrimes if (preen) { 5181558Srgrimes printf(" (SALVAGED)\n"); 5191558Srgrimes idesc->id_fix = FIX; 5201558Srgrimes return (ALTERED); 5211558Srgrimes } 5221558Srgrimes if (reply("SALVAGE") == 0) { 5231558Srgrimes idesc->id_fix = NOFIX; 5241558Srgrimes return (0); 5251558Srgrimes } 5261558Srgrimes idesc->id_fix = FIX; 5271558Srgrimes return (ALTERED); 5281558Srgrimes 5291558Srgrimes case FIX: 5301558Srgrimes return (ALTERED); 5311558Srgrimes 5321558Srgrimes case NOFIX: 5331558Srgrimes case IGNORE: 5341558Srgrimes return (0); 5351558Srgrimes 5361558Srgrimes default: 53723675Speter errx(EEXIT, "UNKNOWN INODESC FIX MODE %d", idesc->id_fix); 5381558Srgrimes } 5391558Srgrimes /* NOTREACHED */ 54023675Speter return (0); 5411558Srgrimes} 5421558Srgrimes 54323675Speter#if __STDC__ 54423675Speter#include <stdarg.h> 54523675Speter#else 54623675Speter#include <varargs.h> 54723675Speter#endif 5481558Srgrimes 5491558Srgrimes/* 5501558Srgrimes * An unexpected inconsistency occured. 5511558Srgrimes * Die if preening, otherwise just print message and continue. 5521558Srgrimes */ 5537585Sbdevoid 55423675Speter#if __STDC__ 55523675Speterpfatal(const char *fmt, ...) 55623675Speter#else 55723675Speterpfatal(fmt, va_alist) 55823675Speter char *fmt; 55923675Speter va_dcl 56023675Speter#endif 5611558Srgrimes{ 5627585Sbde va_list ap; 56323675Speter#if __STDC__ 56423675Speter va_start(ap, fmt); 56523675Speter#else 56623675Speter va_start(ap); 56723675Speter#endif 56823675Speter if (!preen) { 56923675Speter (void)vfprintf(stderr, fmt, ap); 57023675Speter va_end(ap); 57123675Speter return; 5721558Srgrimes } 57323675Speter (void)fprintf(stderr, "%s: ", cdevname); 57423675Speter (void)vfprintf(stderr, fmt, ap); 57523675Speter (void)fprintf(stderr, 57623675Speter "\n%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", 57723675Speter cdevname); 57823675Speter exit(EEXIT); 5791558Srgrimes} 5801558Srgrimes 5811558Srgrimes/* 5821558Srgrimes * Pwarn just prints a message when not preening, 5831558Srgrimes * or a warning (preceded by filename) when preening. 5841558Srgrimes */ 5857585Sbdevoid 58623675Speter#if __STDC__ 58723675Speterpwarn(const char *fmt, ...) 58823675Speter#else 58923675Speterpwarn(fmt, va_alist) 59023675Speter char *fmt; 59123675Speter va_dcl 59223675Speter#endif 5931558Srgrimes{ 5947585Sbde va_list ap; 59523675Speter#if __STDC__ 59623675Speter va_start(ap, fmt); 59723675Speter#else 59823675Speter va_start(ap); 59923675Speter#endif 6001558Srgrimes if (preen) 60123675Speter (void)fprintf(stderr, "%s: ", cdevname); 60223675Speter (void)vfprintf(stderr, fmt, ap); 6037585Sbde va_end(ap); 6041558Srgrimes} 6051558Srgrimes 6061558Srgrimes/* 6071558Srgrimes * Stub for routines from kernel. 6081558Srgrimes */ 60918286Sbdevoid 61023675Speter#if __STDC__ 6117585Sbdepanic(const char *fmt, ...) 6127585Sbde#else 6137585Sbdepanic(fmt, va_alist) 6147585Sbde char *fmt; 61523675Speter va_dcl 6167585Sbde#endif 6171558Srgrimes{ 61823675Speter va_list ap; 61923675Speter#if __STDC__ 62023675Speter va_start(ap, fmt); 62123675Speter#else 62223675Speter va_start(ap); 62323675Speter#endif 6241558Srgrimes pfatal("INTERNAL INCONSISTENCY:"); 62523675Speter (void)vfprintf(stderr, fmt, ap); 62623675Speter va_end(ap); 62723675Speter exit(EEXIT); 6281558Srgrimes} 629