utilities.c revision 23799
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); 901558Srgrimes return (0); 911558Srgrimes } 921558Srgrimes if (yflag || (persevere && nflag)) { 931558Srgrimes printf("%s? yes\n\n", question); 941558Srgrimes return (1); 951558Srgrimes } 961558Srgrimes do { 971558Srgrimes printf("%s? [yn] ", question); 981558Srgrimes (void) fflush(stdout); 991558Srgrimes c = getc(stdin); 1001558Srgrimes while (c != '\n' && getc(stdin) != '\n') 1011558Srgrimes if (feof(stdin)) 1021558Srgrimes return (0); 1031558Srgrimes } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N'); 1041558Srgrimes printf("\n"); 1051558Srgrimes if (c == 'y' || c == 'Y') 1061558Srgrimes return (1); 1071558Srgrimes return (0); 1081558Srgrimes} 1091558Srgrimes 1101558Srgrimes/* 1111558Srgrimes * Malloc buffers and set up cache. 1121558Srgrimes */ 1137585Sbdevoid 1141558Srgrimesbufinit() 1151558Srgrimes{ 1161558Srgrimes register struct bufarea *bp; 1171558Srgrimes long bufcnt, i; 1181558Srgrimes char *bufp; 1191558Srgrimes 1201558Srgrimes pbp = pdirbp = (struct bufarea *)0; 1211558Srgrimes bufp = malloc((unsigned int)sblock.fs_bsize); 1221558Srgrimes if (bufp == 0) 12323675Speter errx(EEXIT, "cannot allocate buffer pool"); 1241558Srgrimes cgblk.b_un.b_buf = bufp; 1251558Srgrimes initbarea(&cgblk); 1261558Srgrimes bufhead.b_next = bufhead.b_prev = &bufhead; 1271558Srgrimes bufcnt = MAXBUFSPACE / sblock.fs_bsize; 1281558Srgrimes if (bufcnt < MINBUFS) 1291558Srgrimes bufcnt = MINBUFS; 1301558Srgrimes for (i = 0; i < bufcnt; i++) { 1311558Srgrimes bp = (struct bufarea *)malloc(sizeof(struct bufarea)); 1321558Srgrimes bufp = malloc((unsigned int)sblock.fs_bsize); 1331558Srgrimes if (bp == NULL || bufp == NULL) { 1341558Srgrimes if (i >= MINBUFS) 1351558Srgrimes break; 13623675Speter errx(EEXIT, "cannot allocate buffer pool"); 1371558Srgrimes } 1381558Srgrimes bp->b_un.b_buf = bufp; 1391558Srgrimes bp->b_prev = &bufhead; 1401558Srgrimes bp->b_next = bufhead.b_next; 1411558Srgrimes bufhead.b_next->b_prev = bp; 1421558Srgrimes bufhead.b_next = bp; 1431558Srgrimes initbarea(bp); 1441558Srgrimes } 1451558Srgrimes bufhead.b_size = i; /* save number of buffers */ 1461558Srgrimes} 1471558Srgrimes 1481558Srgrimes/* 1491558Srgrimes * Manage a cache of directory blocks. 1501558Srgrimes */ 1511558Srgrimesstruct bufarea * 1521558Srgrimesgetdatablk(blkno, size) 15323675Speter ufs_daddr_t blkno; 1541558Srgrimes long size; 1551558Srgrimes{ 1561558Srgrimes register struct bufarea *bp; 1571558Srgrimes 1581558Srgrimes for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next) 1591558Srgrimes if (bp->b_bno == fsbtodb(&sblock, blkno)) 1601558Srgrimes goto foundit; 1611558Srgrimes for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev) 1621558Srgrimes if ((bp->b_flags & B_INUSE) == 0) 1631558Srgrimes break; 1641558Srgrimes if (bp == &bufhead) 16523675Speter errx(EEXIT, "deadlocked buffer pool"); 1661558Srgrimes getblk(bp, blkno, size); 1671558Srgrimes /* fall through */ 1681558Srgrimesfoundit: 1691558Srgrimes totalreads++; 1701558Srgrimes bp->b_prev->b_next = bp->b_next; 1711558Srgrimes bp->b_next->b_prev = bp->b_prev; 1721558Srgrimes bp->b_prev = &bufhead; 1731558Srgrimes bp->b_next = bufhead.b_next; 1741558Srgrimes bufhead.b_next->b_prev = bp; 1751558Srgrimes bufhead.b_next = bp; 1761558Srgrimes bp->b_flags |= B_INUSE; 1771558Srgrimes return (bp); 1781558Srgrimes} 1791558Srgrimes 1801558Srgrimesvoid 1811558Srgrimesgetblk(bp, blk, size) 1821558Srgrimes register struct bufarea *bp; 18323675Speter ufs_daddr_t blk; 1841558Srgrimes long size; 1851558Srgrimes{ 18623675Speter ufs_daddr_t dblk; 1871558Srgrimes 1881558Srgrimes dblk = fsbtodb(&sblock, blk); 1891558Srgrimes if (bp->b_bno != dblk) { 1901558Srgrimes flush(fswritefd, bp); 1911558Srgrimes diskreads++; 1921558Srgrimes bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, dblk, size); 1931558Srgrimes bp->b_bno = dblk; 1941558Srgrimes bp->b_size = size; 1951558Srgrimes } 1961558Srgrimes} 1971558Srgrimes 1987585Sbdevoid 1991558Srgrimesflush(fd, bp) 2001558Srgrimes int fd; 2011558Srgrimes register struct bufarea *bp; 2021558Srgrimes{ 2031558Srgrimes register int i, j; 2041558Srgrimes 2051558Srgrimes if (!bp->b_dirty) 2061558Srgrimes return; 2071558Srgrimes if (bp->b_errs != 0) 2081558Srgrimes pfatal("WRITING %sZERO'ED BLOCK %d TO DISK\n", 2091558Srgrimes (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ", 2101558Srgrimes bp->b_bno); 2111558Srgrimes bp->b_dirty = 0; 2121558Srgrimes bp->b_errs = 0; 2131558Srgrimes bwrite(fd, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size); 2141558Srgrimes if (bp != &sblk) 2151558Srgrimes return; 2161558Srgrimes for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 2171558Srgrimes bwrite(fswritefd, (char *)sblock.fs_csp[j], 2181558Srgrimes fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), 2191558Srgrimes sblock.fs_cssize - i < sblock.fs_bsize ? 2201558Srgrimes sblock.fs_cssize - i : sblock.fs_bsize); 2211558Srgrimes } 2221558Srgrimes} 2231558Srgrimes 22423675Speterstatic void 2251558Srgrimesrwerror(mesg, blk) 2261558Srgrimes char *mesg; 22723675Speter ufs_daddr_t blk; 2281558Srgrimes{ 2291558Srgrimes 2301558Srgrimes if (preen == 0) 2311558Srgrimes printf("\n"); 2321558Srgrimes pfatal("CANNOT %s: BLK %ld", mesg, blk); 2331558Srgrimes if (reply("CONTINUE") == 0) 23423675Speter exit(EEXIT); 2351558Srgrimes} 2361558Srgrimes 2377585Sbdevoid 23823675Speterckfini(markclean) 23923675Speter int markclean; 2401558Srgrimes{ 2411558Srgrimes register struct bufarea *bp, *nbp; 24223675Speter int ofsmodified, cnt = 0; 2431558Srgrimes 2441558Srgrimes if (fswritefd < 0) { 2451558Srgrimes (void)close(fsreadfd); 2461558Srgrimes return; 2471558Srgrimes } 2481558Srgrimes flush(fswritefd, &sblk); 2491558Srgrimes if (havesb && sblk.b_bno != SBOFF / dev_bsize && 2501558Srgrimes !preen && reply("UPDATE STANDARD SUPERBLOCK")) { 2511558Srgrimes sblk.b_bno = SBOFF / dev_bsize; 2521558Srgrimes sbdirty(); 2531558Srgrimes flush(fswritefd, &sblk); 2541558Srgrimes } 2551558Srgrimes flush(fswritefd, &cgblk); 2561558Srgrimes free(cgblk.b_un.b_buf); 2571558Srgrimes for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) { 2581558Srgrimes cnt++; 2591558Srgrimes flush(fswritefd, bp); 2601558Srgrimes nbp = bp->b_prev; 2611558Srgrimes free(bp->b_un.b_buf); 2621558Srgrimes free((char *)bp); 2631558Srgrimes } 2641558Srgrimes if (bufhead.b_size != cnt) 26523675Speter errx(EEXIT, "Panic: lost %d buffers", bufhead.b_size - cnt); 2661558Srgrimes pbp = pdirbp = (struct bufarea *)0; 26723675Speter if (markclean && sblock.fs_clean == 0) { 26823675Speter sblock.fs_clean = 1; 26923675Speter sbdirty(); 27023675Speter ofsmodified = fsmodified; 27123675Speter flush(fswritefd, &sblk); 27223675Speter fsmodified = ofsmodified; 27323675Speter if (!preen) 27423675Speter printf("\n***** FILE SYSTEM MARKED CLEAN *****\n"); 27523675Speter } 2761558Srgrimes if (debug) 2771558Srgrimes printf("cache missed %ld of %ld (%d%%)\n", diskreads, 2781558Srgrimes totalreads, (int)(diskreads * 100 / totalreads)); 2791558Srgrimes (void)close(fsreadfd); 2801558Srgrimes (void)close(fswritefd); 2811558Srgrimes} 2821558Srgrimes 2837585Sbdeint 2841558Srgrimesbread(fd, buf, blk, size) 2851558Srgrimes int fd; 2861558Srgrimes char *buf; 28723675Speter ufs_daddr_t blk; 2881558Srgrimes long size; 2891558Srgrimes{ 2901558Srgrimes char *cp; 2911558Srgrimes int i, errs; 2921558Srgrimes off_t offset; 2931558Srgrimes 2941558Srgrimes offset = blk; 2951558Srgrimes offset *= dev_bsize; 2961558Srgrimes if (lseek(fd, offset, 0) < 0) 2971558Srgrimes rwerror("SEEK", blk); 2981558Srgrimes else if (read(fd, buf, (int)size) == size) 2991558Srgrimes return (0); 3001558Srgrimes rwerror("READ", blk); 3011558Srgrimes if (lseek(fd, offset, 0) < 0) 3021558Srgrimes rwerror("SEEK", blk); 3031558Srgrimes errs = 0; 30423675Speter memset(buf, 0, (size_t)size); 3051558Srgrimes printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:"); 3061558Srgrimes for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) { 3071558Srgrimes if (read(fd, cp, (int)secsize) != secsize) { 3081558Srgrimes (void)lseek(fd, offset + i + secsize, 0); 3091558Srgrimes if (secsize != dev_bsize && dev_bsize != 1) 3101558Srgrimes printf(" %ld (%ld),", 3111558Srgrimes (blk * dev_bsize + i) / secsize, 3121558Srgrimes blk + i / dev_bsize); 3131558Srgrimes else 3141558Srgrimes printf(" %ld,", blk + i / dev_bsize); 3151558Srgrimes errs++; 3161558Srgrimes } 3171558Srgrimes } 3181558Srgrimes printf("\n"); 3191558Srgrimes return (errs); 3201558Srgrimes} 3211558Srgrimes 3227585Sbdevoid 3231558Srgrimesbwrite(fd, buf, blk, size) 3241558Srgrimes int fd; 3251558Srgrimes char *buf; 32623675Speter ufs_daddr_t blk; 3271558Srgrimes long size; 3281558Srgrimes{ 3291558Srgrimes int i; 3301558Srgrimes char *cp; 3311558Srgrimes off_t offset; 3321558Srgrimes 3331558Srgrimes if (fd < 0) 3341558Srgrimes return; 3351558Srgrimes offset = blk; 3361558Srgrimes offset *= dev_bsize; 3371558Srgrimes if (lseek(fd, offset, 0) < 0) 3381558Srgrimes rwerror("SEEK", blk); 3391558Srgrimes else if (write(fd, buf, (int)size) == size) { 3401558Srgrimes fsmodified = 1; 3411558Srgrimes return; 3421558Srgrimes } 3431558Srgrimes rwerror("WRITE", blk); 3441558Srgrimes if (lseek(fd, offset, 0) < 0) 3451558Srgrimes rwerror("SEEK", blk); 3461558Srgrimes printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:"); 3471558Srgrimes for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize) 3481558Srgrimes if (write(fd, cp, (int)dev_bsize) != dev_bsize) { 3491558Srgrimes (void)lseek(fd, offset + i + dev_bsize, 0); 3501558Srgrimes printf(" %ld,", blk + i / dev_bsize); 3511558Srgrimes } 3521558Srgrimes printf("\n"); 3531558Srgrimes return; 3541558Srgrimes} 3551558Srgrimes 3561558Srgrimes/* 3571558Srgrimes * allocate a data block with the specified number of fragments 3581558Srgrimes */ 35923675Speterufs_daddr_t 3601558Srgrimesallocblk(frags) 3611558Srgrimes long frags; 3621558Srgrimes{ 3631558Srgrimes register int i, j, k; 3641558Srgrimes 3651558Srgrimes if (frags <= 0 || frags > sblock.fs_frag) 3661558Srgrimes return (0); 3671558Srgrimes for (i = 0; i < maxfsblock - sblock.fs_frag; i += sblock.fs_frag) { 3681558Srgrimes for (j = 0; j <= sblock.fs_frag - frags; j++) { 3691558Srgrimes if (testbmap(i + j)) 3701558Srgrimes continue; 3711558Srgrimes for (k = 1; k < frags; k++) 3721558Srgrimes if (testbmap(i + j + k)) 3731558Srgrimes break; 3741558Srgrimes if (k < frags) { 3751558Srgrimes j += k; 3761558Srgrimes continue; 3771558Srgrimes } 3781558Srgrimes for (k = 0; k < frags; k++) 3791558Srgrimes setbmap(i + j + k); 3801558Srgrimes n_blks += frags; 3811558Srgrimes return (i + j); 3821558Srgrimes } 3831558Srgrimes } 3841558Srgrimes return (0); 3851558Srgrimes} 3861558Srgrimes 3871558Srgrimes/* 3881558Srgrimes * Free a previously allocated block 3891558Srgrimes */ 3907585Sbdevoid 3911558Srgrimesfreeblk(blkno, frags) 39223675Speter ufs_daddr_t blkno; 3931558Srgrimes long frags; 3941558Srgrimes{ 3951558Srgrimes struct inodesc idesc; 3961558Srgrimes 3971558Srgrimes idesc.id_blkno = blkno; 3981558Srgrimes idesc.id_numfrags = frags; 3991558Srgrimes (void)pass4check(&idesc); 4001558Srgrimes} 4011558Srgrimes 4021558Srgrimes/* 4031558Srgrimes * Find a pathname 4041558Srgrimes */ 4057585Sbdevoid 4061558Srgrimesgetpathname(namebuf, curdir, ino) 4071558Srgrimes char *namebuf; 4081558Srgrimes ino_t curdir, ino; 4091558Srgrimes{ 4101558Srgrimes int len; 4111558Srgrimes register char *cp; 4121558Srgrimes struct inodesc idesc; 4131558Srgrimes static int busy = 0; 4141558Srgrimes 4151558Srgrimes if (curdir == ino && ino == ROOTINO) { 4161558Srgrimes (void)strcpy(namebuf, "/"); 4171558Srgrimes return; 4181558Srgrimes } 4191558Srgrimes if (busy || 4201558Srgrimes (statemap[curdir] != DSTATE && statemap[curdir] != DFOUND)) { 4211558Srgrimes (void)strcpy(namebuf, "?"); 4221558Srgrimes return; 4231558Srgrimes } 4241558Srgrimes busy = 1; 42523675Speter memset(&idesc, 0, sizeof(struct inodesc)); 4261558Srgrimes idesc.id_type = DATA; 4271558Srgrimes idesc.id_fix = IGNORE; 4281558Srgrimes cp = &namebuf[MAXPATHLEN - 1]; 4291558Srgrimes *cp = '\0'; 4301558Srgrimes if (curdir != ino) { 4311558Srgrimes idesc.id_parent = curdir; 4321558Srgrimes goto namelookup; 4331558Srgrimes } 4341558Srgrimes while (ino != ROOTINO) { 4351558Srgrimes idesc.id_number = ino; 4361558Srgrimes idesc.id_func = findino; 4371558Srgrimes idesc.id_name = ".."; 4381558Srgrimes if ((ckinode(ginode(ino), &idesc) & FOUND) == 0) 4391558Srgrimes break; 4401558Srgrimes namelookup: 4411558Srgrimes idesc.id_number = idesc.id_parent; 4421558Srgrimes idesc.id_parent = ino; 4431558Srgrimes idesc.id_func = findname; 4441558Srgrimes idesc.id_name = namebuf; 4451558Srgrimes if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0) 4461558Srgrimes break; 4471558Srgrimes len = strlen(namebuf); 4481558Srgrimes cp -= len; 44923675Speter memmove(cp, namebuf, (size_t)len); 4501558Srgrimes *--cp = '/'; 4511558Srgrimes if (cp < &namebuf[MAXNAMLEN]) 4521558Srgrimes break; 4531558Srgrimes ino = idesc.id_number; 4541558Srgrimes } 4551558Srgrimes busy = 0; 4561558Srgrimes if (ino != ROOTINO) 4571558Srgrimes *--cp = '?'; 45823675Speter memmove(namebuf, cp, (size_t)(&namebuf[MAXPATHLEN] - cp)); 4591558Srgrimes} 4601558Srgrimes 4611558Srgrimesvoid 46223675Spetercatch(sig) 46323675Speter int sig; 4641558Srgrimes{ 4651558Srgrimes if (!doinglevel2) 46623675Speter ckfini(0); 4671558Srgrimes exit(12); 4681558Srgrimes} 4691558Srgrimes 4701558Srgrimes/* 4711558Srgrimes * When preening, allow a single quit to signal 4721558Srgrimes * a special exit after filesystem checks complete 4731558Srgrimes * so that reboot sequence may be interrupted. 4741558Srgrimes */ 4751558Srgrimesvoid 47623675Spetercatchquit(sig) 47723675Speter int sig; 4781558Srgrimes{ 4791558Srgrimes printf("returning to single-user after filesystem check\n"); 4801558Srgrimes returntosingle = 1; 4811558Srgrimes (void)signal(SIGQUIT, SIG_DFL); 4821558Srgrimes} 4831558Srgrimes 4841558Srgrimes/* 4851558Srgrimes * Ignore a single quit signal; wait and flush just in case. 4861558Srgrimes * Used by child processes in preen. 4871558Srgrimes */ 4881558Srgrimesvoid 48923675Spetervoidquit(sig) 49023675Speter int sig; 4911558Srgrimes{ 4921558Srgrimes 4931558Srgrimes sleep(1); 4941558Srgrimes (void)signal(SIGQUIT, SIG_IGN); 4951558Srgrimes (void)signal(SIGQUIT, SIG_DFL); 4961558Srgrimes} 4971558Srgrimes 4981558Srgrimes/* 4991558Srgrimes * determine whether an inode should be fixed. 5001558Srgrimes */ 5017585Sbdeint 5021558Srgrimesdofix(idesc, msg) 5031558Srgrimes register struct inodesc *idesc; 5041558Srgrimes char *msg; 5051558Srgrimes{ 5061558Srgrimes 5071558Srgrimes switch (idesc->id_fix) { 5081558Srgrimes 5091558Srgrimes case DONTKNOW: 5101558Srgrimes if (idesc->id_type == DATA) 5111558Srgrimes direrror(idesc->id_number, msg); 5121558Srgrimes else 5131558Srgrimes pwarn(msg); 5141558Srgrimes if (preen) { 5151558Srgrimes printf(" (SALVAGED)\n"); 5161558Srgrimes idesc->id_fix = FIX; 5171558Srgrimes return (ALTERED); 5181558Srgrimes } 5191558Srgrimes if (reply("SALVAGE") == 0) { 5201558Srgrimes idesc->id_fix = NOFIX; 5211558Srgrimes return (0); 5221558Srgrimes } 5231558Srgrimes idesc->id_fix = FIX; 5241558Srgrimes return (ALTERED); 5251558Srgrimes 5261558Srgrimes case FIX: 5271558Srgrimes return (ALTERED); 5281558Srgrimes 5291558Srgrimes case NOFIX: 5301558Srgrimes case IGNORE: 5311558Srgrimes return (0); 5321558Srgrimes 5331558Srgrimes default: 53423675Speter errx(EEXIT, "UNKNOWN INODESC FIX MODE %d", idesc->id_fix); 5351558Srgrimes } 5361558Srgrimes /* NOTREACHED */ 53723675Speter return (0); 5381558Srgrimes} 5391558Srgrimes 54023675Speter#if __STDC__ 54123675Speter#include <stdarg.h> 54223675Speter#else 54323675Speter#include <varargs.h> 54423675Speter#endif 5451558Srgrimes 5461558Srgrimes/* 5471558Srgrimes * An unexpected inconsistency occured. 5481558Srgrimes * Die if preening, otherwise just print message and continue. 5491558Srgrimes */ 5507585Sbdevoid 55123675Speter#if __STDC__ 55223675Speterpfatal(const char *fmt, ...) 55323675Speter#else 55423675Speterpfatal(fmt, va_alist) 55523675Speter char *fmt; 55623675Speter va_dcl 55723675Speter#endif 5581558Srgrimes{ 5597585Sbde va_list ap; 56023675Speter#if __STDC__ 56123675Speter va_start(ap, fmt); 56223675Speter#else 56323675Speter va_start(ap); 56423675Speter#endif 56523675Speter if (!preen) { 56623675Speter (void)vfprintf(stderr, fmt, ap); 56723675Speter va_end(ap); 56823675Speter return; 5691558Srgrimes } 57023675Speter (void)fprintf(stderr, "%s: ", cdevname); 57123675Speter (void)vfprintf(stderr, fmt, ap); 57223675Speter (void)fprintf(stderr, 57323675Speter "\n%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", 57423675Speter cdevname); 57523675Speter exit(EEXIT); 5761558Srgrimes} 5771558Srgrimes 5781558Srgrimes/* 5791558Srgrimes * Pwarn just prints a message when not preening, 5801558Srgrimes * or a warning (preceded by filename) when preening. 5811558Srgrimes */ 5827585Sbdevoid 58323675Speter#if __STDC__ 58423675Speterpwarn(const char *fmt, ...) 58523675Speter#else 58623675Speterpwarn(fmt, va_alist) 58723675Speter char *fmt; 58823675Speter va_dcl 58923675Speter#endif 5901558Srgrimes{ 5917585Sbde va_list ap; 59223675Speter#if __STDC__ 59323675Speter va_start(ap, fmt); 59423675Speter#else 59523675Speter va_start(ap); 59623675Speter#endif 5971558Srgrimes if (preen) 59823675Speter (void)fprintf(stderr, "%s: ", cdevname); 59923675Speter (void)vfprintf(stderr, fmt, ap); 6007585Sbde va_end(ap); 6011558Srgrimes} 6021558Srgrimes 6031558Srgrimes/* 6041558Srgrimes * Stub for routines from kernel. 6051558Srgrimes */ 60618286Sbdevoid 60723675Speter#if __STDC__ 6087585Sbdepanic(const char *fmt, ...) 6097585Sbde#else 6107585Sbdepanic(fmt, va_alist) 6117585Sbde char *fmt; 61223675Speter va_dcl 6137585Sbde#endif 6141558Srgrimes{ 61523675Speter va_list ap; 61623675Speter#if __STDC__ 61723675Speter va_start(ap, fmt); 61823675Speter#else 61923675Speter va_start(ap); 62023675Speter#endif 6211558Srgrimes pfatal("INTERNAL INCONSISTENCY:"); 62223675Speter (void)vfprintf(stderr, fmt, ap); 62323675Speter va_end(ap); 62423675Speter exit(EEXIT); 6251558Srgrimes} 626