utilities.c revision 41477
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 3541477Sjulian#if 0 3623675Speterstatic const char sccsid[] = "@(#)utilities.c 8.6 (Berkeley) 5/19/95"; 3741477Sjulian#endif 3841477Sjulianstatic const char rcsid[] = 3941477Sjulian "$Id: utilities.c,v 1.8 1998/06/15 07:07:21 charnier Exp $"; 401558Srgrimes#endif /* not lint */ 411558Srgrimes 421558Srgrimes#include <sys/param.h> 4323675Speter 441558Srgrimes#include <ufs/ufs/dinode.h> 451558Srgrimes#include <ufs/ufs/dir.h> 461558Srgrimes#include <ufs/ffs/fs.h> 4723799Sbde 4823675Speter#include <err.h> 4923799Sbde#include <string.h> 5023675Speter 511558Srgrimes#include "fsck.h" 521558Srgrimes 531558Srgrimeslong diskreads, totalreads; /* Disk cache statistics */ 541558Srgrimes 5523675Speterstatic void rwerror __P((char *mesg, ufs_daddr_t blk)); 567585Sbde 577585Sbdeint 581558Srgrimesftypeok(dp) 591558Srgrimes struct dinode *dp; 601558Srgrimes{ 611558Srgrimes switch (dp->di_mode & IFMT) { 621558Srgrimes 631558Srgrimes case IFDIR: 641558Srgrimes case IFREG: 651558Srgrimes case IFBLK: 661558Srgrimes case IFCHR: 671558Srgrimes case IFLNK: 681558Srgrimes case IFSOCK: 691558Srgrimes case IFIFO: 701558Srgrimes return (1); 711558Srgrimes 721558Srgrimes default: 731558Srgrimes if (debug) 741558Srgrimes printf("bad file type 0%o\n", dp->di_mode); 751558Srgrimes return (0); 761558Srgrimes } 771558Srgrimes} 781558Srgrimes 797585Sbdeint 801558Srgrimesreply(question) 811558Srgrimes char *question; 821558Srgrimes{ 831558Srgrimes int persevere; 841558Srgrimes char c; 851558Srgrimes 861558Srgrimes if (preen) 871558Srgrimes pfatal("INTERNAL ERROR: GOT TO reply()"); 881558Srgrimes persevere = !strcmp(question, "CONTINUE"); 891558Srgrimes printf("\n"); 901558Srgrimes if (!persevere && (nflag || fswritefd < 0)) { 911558Srgrimes printf("%s? no\n\n", question); 9234266Sjulian resolved = 0; 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); 10334266Sjulian while (c != '\n' && getc(stdin) != '\n') { 10434266Sjulian if (feof(stdin)) { 10534266Sjulian resolved = 0; 1061558Srgrimes return (0); 10734266Sjulian } 10834266Sjulian } 1091558Srgrimes } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N'); 1101558Srgrimes printf("\n"); 1111558Srgrimes if (c == 'y' || c == 'Y') 1121558Srgrimes return (1); 11334266Sjulian resolved = 0; 1141558Srgrimes return (0); 1151558Srgrimes} 1161558Srgrimes 1171558Srgrimes/* 11841474Sjulian * Look up state information for an inode. 11941474Sjulian */ 12041474Sjulianstruct inostat * 12141474Sjulianinoinfo(inum) 12241474Sjulian ino_t inum; 12341474Sjulian{ 12441474Sjulian static struct inostat unallocated = { USTATE, 0, 0 }; 12541474Sjulian struct inostatlist *ilp; 12641474Sjulian int iloff; 12741474Sjulian 12841474Sjulian if (inum > maxino) 12941474Sjulian errx(EEXIT, "inoinfo: inumber %d out of range", inum); 13041474Sjulian ilp = &inostathead[inum / sblock.fs_ipg]; 13141474Sjulian iloff = inum % sblock.fs_ipg; 13241474Sjulian if (iloff >= ilp->il_numalloced) 13341474Sjulian return (&unallocated); 13441474Sjulian return (&ilp->il_stat[iloff]); 13541474Sjulian} 13641474Sjulian 13741474Sjulian/* 1381558Srgrimes * Malloc buffers and set up cache. 1391558Srgrimes */ 1407585Sbdevoid 1411558Srgrimesbufinit() 1421558Srgrimes{ 1431558Srgrimes register struct bufarea *bp; 1441558Srgrimes long bufcnt, i; 1451558Srgrimes char *bufp; 1461558Srgrimes 1471558Srgrimes pbp = pdirbp = (struct bufarea *)0; 1481558Srgrimes bufp = malloc((unsigned int)sblock.fs_bsize); 1491558Srgrimes if (bufp == 0) 15023675Speter errx(EEXIT, "cannot allocate buffer pool"); 1511558Srgrimes cgblk.b_un.b_buf = bufp; 1521558Srgrimes initbarea(&cgblk); 1531558Srgrimes bufhead.b_next = bufhead.b_prev = &bufhead; 1541558Srgrimes bufcnt = MAXBUFSPACE / sblock.fs_bsize; 1551558Srgrimes if (bufcnt < MINBUFS) 1561558Srgrimes bufcnt = MINBUFS; 1571558Srgrimes for (i = 0; i < bufcnt; i++) { 1581558Srgrimes bp = (struct bufarea *)malloc(sizeof(struct bufarea)); 1591558Srgrimes bufp = malloc((unsigned int)sblock.fs_bsize); 1601558Srgrimes if (bp == NULL || bufp == NULL) { 1611558Srgrimes if (i >= MINBUFS) 1621558Srgrimes break; 16323675Speter errx(EEXIT, "cannot allocate buffer pool"); 1641558Srgrimes } 1651558Srgrimes bp->b_un.b_buf = bufp; 1661558Srgrimes bp->b_prev = &bufhead; 1671558Srgrimes bp->b_next = bufhead.b_next; 1681558Srgrimes bufhead.b_next->b_prev = bp; 1691558Srgrimes bufhead.b_next = bp; 1701558Srgrimes initbarea(bp); 1711558Srgrimes } 1721558Srgrimes bufhead.b_size = i; /* save number of buffers */ 1731558Srgrimes} 1741558Srgrimes 1751558Srgrimes/* 1761558Srgrimes * Manage a cache of directory blocks. 1771558Srgrimes */ 1781558Srgrimesstruct bufarea * 1791558Srgrimesgetdatablk(blkno, size) 18023675Speter ufs_daddr_t blkno; 1811558Srgrimes long size; 1821558Srgrimes{ 1831558Srgrimes register struct bufarea *bp; 1841558Srgrimes 1851558Srgrimes for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next) 1861558Srgrimes if (bp->b_bno == fsbtodb(&sblock, blkno)) 1871558Srgrimes goto foundit; 1881558Srgrimes for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev) 1891558Srgrimes if ((bp->b_flags & B_INUSE) == 0) 1901558Srgrimes break; 1911558Srgrimes if (bp == &bufhead) 19223675Speter errx(EEXIT, "deadlocked buffer pool"); 1931558Srgrimes getblk(bp, blkno, size); 1941558Srgrimes /* fall through */ 1951558Srgrimesfoundit: 1961558Srgrimes totalreads++; 1971558Srgrimes bp->b_prev->b_next = bp->b_next; 1981558Srgrimes bp->b_next->b_prev = bp->b_prev; 1991558Srgrimes bp->b_prev = &bufhead; 2001558Srgrimes bp->b_next = bufhead.b_next; 2011558Srgrimes bufhead.b_next->b_prev = bp; 2021558Srgrimes bufhead.b_next = bp; 2031558Srgrimes bp->b_flags |= B_INUSE; 2041558Srgrimes return (bp); 2051558Srgrimes} 2061558Srgrimes 2071558Srgrimesvoid 2081558Srgrimesgetblk(bp, blk, size) 2091558Srgrimes register struct bufarea *bp; 21023675Speter ufs_daddr_t blk; 2111558Srgrimes long size; 2121558Srgrimes{ 21323675Speter ufs_daddr_t dblk; 2141558Srgrimes 2151558Srgrimes dblk = fsbtodb(&sblock, blk); 2161558Srgrimes if (bp->b_bno != dblk) { 2171558Srgrimes flush(fswritefd, bp); 2181558Srgrimes diskreads++; 2191558Srgrimes bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, dblk, size); 2201558Srgrimes bp->b_bno = dblk; 2211558Srgrimes bp->b_size = size; 2221558Srgrimes } 2231558Srgrimes} 2241558Srgrimes 2257585Sbdevoid 2261558Srgrimesflush(fd, bp) 2271558Srgrimes int fd; 2281558Srgrimes register struct bufarea *bp; 2291558Srgrimes{ 2301558Srgrimes register int i, j; 2311558Srgrimes 2321558Srgrimes if (!bp->b_dirty) 2331558Srgrimes return; 2341558Srgrimes if (bp->b_errs != 0) 2351558Srgrimes pfatal("WRITING %sZERO'ED BLOCK %d TO DISK\n", 2361558Srgrimes (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ", 2371558Srgrimes bp->b_bno); 2381558Srgrimes bp->b_dirty = 0; 2391558Srgrimes bp->b_errs = 0; 2401558Srgrimes bwrite(fd, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size); 2411558Srgrimes if (bp != &sblk) 2421558Srgrimes return; 2431558Srgrimes for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 2441558Srgrimes bwrite(fswritefd, (char *)sblock.fs_csp[j], 2451558Srgrimes fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), 2461558Srgrimes sblock.fs_cssize - i < sblock.fs_bsize ? 2471558Srgrimes sblock.fs_cssize - i : sblock.fs_bsize); 2481558Srgrimes } 2491558Srgrimes} 2501558Srgrimes 25123675Speterstatic void 2521558Srgrimesrwerror(mesg, blk) 2531558Srgrimes char *mesg; 25423675Speter ufs_daddr_t blk; 2551558Srgrimes{ 2561558Srgrimes 2571558Srgrimes if (preen == 0) 2581558Srgrimes printf("\n"); 2591558Srgrimes pfatal("CANNOT %s: BLK %ld", mesg, blk); 2601558Srgrimes if (reply("CONTINUE") == 0) 26123675Speter exit(EEXIT); 2621558Srgrimes} 2631558Srgrimes 2647585Sbdevoid 26523675Speterckfini(markclean) 26623675Speter int markclean; 2671558Srgrimes{ 2681558Srgrimes register struct bufarea *bp, *nbp; 26923675Speter int ofsmodified, cnt = 0; 2701558Srgrimes 2711558Srgrimes if (fswritefd < 0) { 2721558Srgrimes (void)close(fsreadfd); 2731558Srgrimes return; 2741558Srgrimes } 2751558Srgrimes flush(fswritefd, &sblk); 2761558Srgrimes if (havesb && sblk.b_bno != SBOFF / dev_bsize && 2771558Srgrimes !preen && reply("UPDATE STANDARD SUPERBLOCK")) { 2781558Srgrimes sblk.b_bno = SBOFF / dev_bsize; 2791558Srgrimes sbdirty(); 2801558Srgrimes flush(fswritefd, &sblk); 2811558Srgrimes } 2821558Srgrimes flush(fswritefd, &cgblk); 2831558Srgrimes free(cgblk.b_un.b_buf); 2841558Srgrimes for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) { 2851558Srgrimes cnt++; 2861558Srgrimes flush(fswritefd, bp); 2871558Srgrimes nbp = bp->b_prev; 2881558Srgrimes free(bp->b_un.b_buf); 2891558Srgrimes free((char *)bp); 2901558Srgrimes } 2911558Srgrimes if (bufhead.b_size != cnt) 29241477Sjulian errx(EEXIT, "panic: lost %d buffers", bufhead.b_size - cnt); 2931558Srgrimes pbp = pdirbp = (struct bufarea *)0; 29441474Sjulian if (sblock.fs_clean != markclean) { 29541474Sjulian sblock.fs_clean = markclean; 29623675Speter sbdirty(); 29723675Speter ofsmodified = fsmodified; 29823675Speter flush(fswritefd, &sblk); 29923675Speter fsmodified = ofsmodified; 30041474Sjulian if (!preen) { 30141474Sjulian printf("\n***** FILE SYSTEM MARKED %s *****\n", 30241474Sjulian markclean ? "CLEAN" : "DIRTY"); 30341474Sjulian if (!markclean) 30441474Sjulian rerun = 1; 30541474Sjulian } 30641474Sjulian } else if (!preen && !markclean) { 30741474Sjulian printf("\n***** FILE SYSTEM STILL DIRTY *****\n"); 30841474Sjulian rerun = 1; 30923675Speter } 3101558Srgrimes if (debug) 3111558Srgrimes printf("cache missed %ld of %ld (%d%%)\n", diskreads, 3121558Srgrimes totalreads, (int)(diskreads * 100 / totalreads)); 3131558Srgrimes (void)close(fsreadfd); 3141558Srgrimes (void)close(fswritefd); 3151558Srgrimes} 3161558Srgrimes 3177585Sbdeint 3181558Srgrimesbread(fd, buf, blk, size) 3191558Srgrimes int fd; 3201558Srgrimes char *buf; 32123675Speter ufs_daddr_t blk; 3221558Srgrimes long size; 3231558Srgrimes{ 3241558Srgrimes char *cp; 3251558Srgrimes int i, errs; 3261558Srgrimes off_t offset; 3271558Srgrimes 3281558Srgrimes offset = blk; 3291558Srgrimes offset *= dev_bsize; 3301558Srgrimes if (lseek(fd, offset, 0) < 0) 3311558Srgrimes rwerror("SEEK", blk); 3321558Srgrimes else if (read(fd, buf, (int)size) == size) 3331558Srgrimes return (0); 3341558Srgrimes rwerror("READ", blk); 3351558Srgrimes if (lseek(fd, offset, 0) < 0) 3361558Srgrimes rwerror("SEEK", blk); 3371558Srgrimes errs = 0; 33823675Speter memset(buf, 0, (size_t)size); 3391558Srgrimes printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:"); 3401558Srgrimes for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) { 3411558Srgrimes if (read(fd, cp, (int)secsize) != secsize) { 3421558Srgrimes (void)lseek(fd, offset + i + secsize, 0); 3431558Srgrimes if (secsize != dev_bsize && dev_bsize != 1) 3441558Srgrimes printf(" %ld (%ld),", 3451558Srgrimes (blk * dev_bsize + i) / secsize, 3461558Srgrimes blk + i / dev_bsize); 3471558Srgrimes else 3481558Srgrimes printf(" %ld,", blk + i / dev_bsize); 3491558Srgrimes errs++; 3501558Srgrimes } 3511558Srgrimes } 3521558Srgrimes printf("\n"); 35341474Sjulian if (errs) 35441474Sjulian resolved = 0; 3551558Srgrimes return (errs); 3561558Srgrimes} 3571558Srgrimes 3587585Sbdevoid 3591558Srgrimesbwrite(fd, buf, blk, size) 3601558Srgrimes int fd; 3611558Srgrimes char *buf; 36223675Speter ufs_daddr_t blk; 3631558Srgrimes long size; 3641558Srgrimes{ 3651558Srgrimes int i; 3661558Srgrimes char *cp; 3671558Srgrimes off_t offset; 3681558Srgrimes 3691558Srgrimes if (fd < 0) 3701558Srgrimes return; 3711558Srgrimes offset = blk; 3721558Srgrimes offset *= dev_bsize; 3731558Srgrimes if (lseek(fd, offset, 0) < 0) 3741558Srgrimes rwerror("SEEK", blk); 3751558Srgrimes else if (write(fd, buf, (int)size) == size) { 3761558Srgrimes fsmodified = 1; 3771558Srgrimes return; 3781558Srgrimes } 37941474Sjulian resolved = 0; 3801558Srgrimes rwerror("WRITE", blk); 3811558Srgrimes if (lseek(fd, offset, 0) < 0) 3821558Srgrimes rwerror("SEEK", blk); 3831558Srgrimes printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:"); 3841558Srgrimes for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize) 3851558Srgrimes if (write(fd, cp, (int)dev_bsize) != dev_bsize) { 3861558Srgrimes (void)lseek(fd, offset + i + dev_bsize, 0); 3871558Srgrimes printf(" %ld,", blk + i / dev_bsize); 3881558Srgrimes } 3891558Srgrimes printf("\n"); 3901558Srgrimes return; 3911558Srgrimes} 3921558Srgrimes 3931558Srgrimes/* 3941558Srgrimes * allocate a data block with the specified number of fragments 3951558Srgrimes */ 39623675Speterufs_daddr_t 3971558Srgrimesallocblk(frags) 3981558Srgrimes long frags; 3991558Srgrimes{ 40034266Sjulian int i, j, k, cg, baseblk; 40134266Sjulian struct cg *cgp = &cgrp; 4021558Srgrimes 4031558Srgrimes if (frags <= 0 || frags > sblock.fs_frag) 4041558Srgrimes return (0); 4051558Srgrimes for (i = 0; i < maxfsblock - sblock.fs_frag; i += sblock.fs_frag) { 4061558Srgrimes for (j = 0; j <= sblock.fs_frag - frags; j++) { 4071558Srgrimes if (testbmap(i + j)) 4081558Srgrimes continue; 4091558Srgrimes for (k = 1; k < frags; k++) 4101558Srgrimes if (testbmap(i + j + k)) 4111558Srgrimes break; 4121558Srgrimes if (k < frags) { 4131558Srgrimes j += k; 4141558Srgrimes continue; 4151558Srgrimes } 41634266Sjulian cg = dtog(&sblock, i + j); 41734266Sjulian getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize); 41834266Sjulian if (!cg_chkmagic(cgp)) 41934266Sjulian pfatal("CG %d: BAD MAGIC NUMBER\n", cg); 42034266Sjulian baseblk = dtogd(&sblock, i + j); 42134266Sjulian for (k = 0; k < frags; k++) { 4221558Srgrimes setbmap(i + j + k); 42334266Sjulian clrbit(cg_blksfree(cgp), baseblk + k); 42434266Sjulian } 4251558Srgrimes n_blks += frags; 42634266Sjulian if (frags == sblock.fs_frag) 42734266Sjulian cgp->cg_cs.cs_nbfree--; 42834266Sjulian else 42934266Sjulian cgp->cg_cs.cs_nffree -= frags; 43034266Sjulian cgdirty(); 4311558Srgrimes return (i + j); 4321558Srgrimes } 4331558Srgrimes } 4341558Srgrimes return (0); 4351558Srgrimes} 4361558Srgrimes 4371558Srgrimes/* 4381558Srgrimes * Free a previously allocated block 4391558Srgrimes */ 4407585Sbdevoid 4411558Srgrimesfreeblk(blkno, frags) 44223675Speter ufs_daddr_t blkno; 4431558Srgrimes long frags; 4441558Srgrimes{ 4451558Srgrimes struct inodesc idesc; 4461558Srgrimes 4471558Srgrimes idesc.id_blkno = blkno; 4481558Srgrimes idesc.id_numfrags = frags; 4491558Srgrimes (void)pass4check(&idesc); 4501558Srgrimes} 4511558Srgrimes 4521558Srgrimes/* 4531558Srgrimes * Find a pathname 4541558Srgrimes */ 4557585Sbdevoid 4561558Srgrimesgetpathname(namebuf, curdir, ino) 4571558Srgrimes char *namebuf; 4581558Srgrimes ino_t curdir, ino; 4591558Srgrimes{ 4601558Srgrimes int len; 4611558Srgrimes register char *cp; 4621558Srgrimes struct inodesc idesc; 4631558Srgrimes static int busy = 0; 4641558Srgrimes 4651558Srgrimes if (curdir == ino && ino == ROOTINO) { 4661558Srgrimes (void)strcpy(namebuf, "/"); 4671558Srgrimes return; 4681558Srgrimes } 4691558Srgrimes if (busy || 47041474Sjulian (inoinfo(curdir)->ino_state != DSTATE && 47141474Sjulian inoinfo(curdir)->ino_state != DFOUND)) { 4721558Srgrimes (void)strcpy(namebuf, "?"); 4731558Srgrimes return; 4741558Srgrimes } 4751558Srgrimes busy = 1; 47623675Speter memset(&idesc, 0, sizeof(struct inodesc)); 4771558Srgrimes idesc.id_type = DATA; 4781558Srgrimes idesc.id_fix = IGNORE; 4791558Srgrimes cp = &namebuf[MAXPATHLEN - 1]; 4801558Srgrimes *cp = '\0'; 4811558Srgrimes if (curdir != ino) { 4821558Srgrimes idesc.id_parent = curdir; 4831558Srgrimes goto namelookup; 4841558Srgrimes } 4851558Srgrimes while (ino != ROOTINO) { 4861558Srgrimes idesc.id_number = ino; 4871558Srgrimes idesc.id_func = findino; 4881558Srgrimes idesc.id_name = ".."; 4891558Srgrimes if ((ckinode(ginode(ino), &idesc) & FOUND) == 0) 4901558Srgrimes break; 4911558Srgrimes namelookup: 4921558Srgrimes idesc.id_number = idesc.id_parent; 4931558Srgrimes idesc.id_parent = ino; 4941558Srgrimes idesc.id_func = findname; 4951558Srgrimes idesc.id_name = namebuf; 4961558Srgrimes if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0) 4971558Srgrimes break; 4981558Srgrimes len = strlen(namebuf); 4991558Srgrimes cp -= len; 50023675Speter memmove(cp, namebuf, (size_t)len); 5011558Srgrimes *--cp = '/'; 5021558Srgrimes if (cp < &namebuf[MAXNAMLEN]) 5031558Srgrimes break; 5041558Srgrimes ino = idesc.id_number; 5051558Srgrimes } 5061558Srgrimes busy = 0; 5071558Srgrimes if (ino != ROOTINO) 5081558Srgrimes *--cp = '?'; 50923675Speter memmove(namebuf, cp, (size_t)(&namebuf[MAXPATHLEN] - cp)); 5101558Srgrimes} 5111558Srgrimes 5121558Srgrimesvoid 51323675Spetercatch(sig) 51423675Speter int sig; 5151558Srgrimes{ 5161558Srgrimes if (!doinglevel2) 51723675Speter ckfini(0); 5181558Srgrimes exit(12); 5191558Srgrimes} 5201558Srgrimes 5211558Srgrimes/* 5221558Srgrimes * When preening, allow a single quit to signal 5231558Srgrimes * a special exit after filesystem checks complete 5241558Srgrimes * so that reboot sequence may be interrupted. 5251558Srgrimes */ 5261558Srgrimesvoid 52723675Spetercatchquit(sig) 52823675Speter int sig; 5291558Srgrimes{ 5301558Srgrimes printf("returning to single-user after filesystem check\n"); 5311558Srgrimes returntosingle = 1; 5321558Srgrimes (void)signal(SIGQUIT, SIG_DFL); 5331558Srgrimes} 5341558Srgrimes 5351558Srgrimes/* 5361558Srgrimes * Ignore a single quit signal; wait and flush just in case. 5371558Srgrimes * Used by child processes in preen. 5381558Srgrimes */ 5391558Srgrimesvoid 54023675Spetervoidquit(sig) 54123675Speter int sig; 5421558Srgrimes{ 5431558Srgrimes 5441558Srgrimes sleep(1); 5451558Srgrimes (void)signal(SIGQUIT, SIG_IGN); 5461558Srgrimes (void)signal(SIGQUIT, SIG_DFL); 5471558Srgrimes} 5481558Srgrimes 5491558Srgrimes/* 5501558Srgrimes * determine whether an inode should be fixed. 5511558Srgrimes */ 5527585Sbdeint 5531558Srgrimesdofix(idesc, msg) 5541558Srgrimes register struct inodesc *idesc; 5551558Srgrimes char *msg; 5561558Srgrimes{ 5571558Srgrimes 5581558Srgrimes switch (idesc->id_fix) { 5591558Srgrimes 5601558Srgrimes case DONTKNOW: 5611558Srgrimes if (idesc->id_type == DATA) 5621558Srgrimes direrror(idesc->id_number, msg); 5631558Srgrimes else 5641558Srgrimes pwarn(msg); 5651558Srgrimes if (preen) { 5661558Srgrimes printf(" (SALVAGED)\n"); 5671558Srgrimes idesc->id_fix = FIX; 5681558Srgrimes return (ALTERED); 5691558Srgrimes } 5701558Srgrimes if (reply("SALVAGE") == 0) { 5711558Srgrimes idesc->id_fix = NOFIX; 5721558Srgrimes return (0); 5731558Srgrimes } 5741558Srgrimes idesc->id_fix = FIX; 5751558Srgrimes return (ALTERED); 5761558Srgrimes 5771558Srgrimes case FIX: 5781558Srgrimes return (ALTERED); 5791558Srgrimes 5801558Srgrimes case NOFIX: 5811558Srgrimes case IGNORE: 5821558Srgrimes return (0); 5831558Srgrimes 5841558Srgrimes default: 58523675Speter errx(EEXIT, "UNKNOWN INODESC FIX MODE %d", idesc->id_fix); 5861558Srgrimes } 5871558Srgrimes /* NOTREACHED */ 58823675Speter return (0); 5891558Srgrimes} 5901558Srgrimes 59123675Speter#if __STDC__ 59223675Speter#include <stdarg.h> 59323675Speter#else 59423675Speter#include <varargs.h> 59523675Speter#endif 5961558Srgrimes 5971558Srgrimes/* 5981558Srgrimes * An unexpected inconsistency occured. 59934266Sjulian * Die if preening or filesystem is running with soft dependency protocol, 60034266Sjulian * otherwise just print message and continue. 6011558Srgrimes */ 6027585Sbdevoid 60323675Speter#if __STDC__ 60423675Speterpfatal(const char *fmt, ...) 60523675Speter#else 60623675Speterpfatal(fmt, va_alist) 60723675Speter char *fmt; 60823675Speter va_dcl 60923675Speter#endif 6101558Srgrimes{ 6117585Sbde va_list ap; 61223675Speter#if __STDC__ 61323675Speter va_start(ap, fmt); 61423675Speter#else 61523675Speter va_start(ap); 61623675Speter#endif 61723675Speter if (!preen) { 61823675Speter (void)vfprintf(stderr, fmt, ap); 61923675Speter va_end(ap); 62034266Sjulian if (usedsoftdep) 62134266Sjulian (void)fprintf(stderr, 62241474Sjulian "\nUNEXPECTED SOFT UPDATE INCONSISTENCY\n"); 62323675Speter return; 6241558Srgrimes } 62541474Sjulian if (cdevname == NULL) 62641474Sjulian cdevname = "fsck"; 62723675Speter (void)fprintf(stderr, "%s: ", cdevname); 62823675Speter (void)vfprintf(stderr, fmt, ap); 62923675Speter (void)fprintf(stderr, 63034266Sjulian "\n%s: UNEXPECTED%sINCONSISTENCY; RUN fsck MANUALLY.\n", 63141474Sjulian cdevname, usedsoftdep ? " SOFT UPDATE " : " "); 63234266Sjulian ckfini(0); 63323675Speter exit(EEXIT); 6341558Srgrimes} 6351558Srgrimes 6361558Srgrimes/* 63734266Sjulian * Pwarn just prints a message when not preening or running soft dependency 63834266Sjulian * protocol, or a warning (preceded by filename) when preening. 6391558Srgrimes */ 6407585Sbdevoid 64123675Speter#if __STDC__ 64223675Speterpwarn(const char *fmt, ...) 64323675Speter#else 64423675Speterpwarn(fmt, va_alist) 64523675Speter char *fmt; 64623675Speter va_dcl 64723675Speter#endif 6481558Srgrimes{ 6497585Sbde va_list ap; 65023675Speter#if __STDC__ 65123675Speter va_start(ap, fmt); 65223675Speter#else 65323675Speter va_start(ap); 65423675Speter#endif 6551558Srgrimes if (preen) 65623675Speter (void)fprintf(stderr, "%s: ", cdevname); 65723675Speter (void)vfprintf(stderr, fmt, ap); 6587585Sbde va_end(ap); 6591558Srgrimes} 6601558Srgrimes 6611558Srgrimes/* 6621558Srgrimes * Stub for routines from kernel. 6631558Srgrimes */ 66418286Sbdevoid 66523675Speter#if __STDC__ 6667585Sbdepanic(const char *fmt, ...) 6677585Sbde#else 6687585Sbdepanic(fmt, va_alist) 6697585Sbde char *fmt; 67023675Speter va_dcl 6717585Sbde#endif 6721558Srgrimes{ 67323675Speter va_list ap; 67423675Speter#if __STDC__ 67523675Speter va_start(ap, fmt); 67623675Speter#else 67723675Speter va_start(ap); 67823675Speter#endif 6791558Srgrimes pfatal("INTERNAL INCONSISTENCY:"); 68023675Speter (void)vfprintf(stderr, fmt, ap); 68123675Speter va_end(ap); 68223675Speter exit(EEXIT); 6831558Srgrimes} 684