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