utilities.c revision 41474
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> 3941474Sjulian#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 <err.h> 4623799Sbde#include <string.h> 4723675Speter 481558Srgrimes#include "fsck.h" 491558Srgrimes 501558Srgrimeslong diskreads, totalreads; /* Disk cache statistics */ 511558Srgrimes 5223675Speterstatic void rwerror __P((char *mesg, ufs_daddr_t blk)); 537585Sbde 547585Sbdeint 551558Srgrimesftypeok(dp) 561558Srgrimes struct dinode *dp; 571558Srgrimes{ 581558Srgrimes switch (dp->di_mode & IFMT) { 591558Srgrimes 601558Srgrimes case IFDIR: 611558Srgrimes case IFREG: 621558Srgrimes case IFBLK: 631558Srgrimes case IFCHR: 641558Srgrimes case IFLNK: 651558Srgrimes case IFSOCK: 661558Srgrimes case IFIFO: 671558Srgrimes return (1); 681558Srgrimes 691558Srgrimes default: 701558Srgrimes if (debug) 711558Srgrimes printf("bad file type 0%o\n", dp->di_mode); 721558Srgrimes return (0); 731558Srgrimes } 741558Srgrimes} 751558Srgrimes 767585Sbdeint 771558Srgrimesreply(question) 781558Srgrimes char *question; 791558Srgrimes{ 801558Srgrimes int persevere; 811558Srgrimes char c; 821558Srgrimes 831558Srgrimes if (preen) 841558Srgrimes pfatal("INTERNAL ERROR: GOT TO reply()"); 851558Srgrimes persevere = !strcmp(question, "CONTINUE"); 861558Srgrimes printf("\n"); 871558Srgrimes if (!persevere && (nflag || fswritefd < 0)) { 881558Srgrimes printf("%s? no\n\n", question); 8934266Sjulian resolved = 0; 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); 10034266Sjulian while (c != '\n' && getc(stdin) != '\n') { 10134266Sjulian if (feof(stdin)) { 10234266Sjulian resolved = 0; 1031558Srgrimes return (0); 10434266Sjulian } 10534266Sjulian } 1061558Srgrimes } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N'); 1071558Srgrimes printf("\n"); 1081558Srgrimes if (c == 'y' || c == 'Y') 1091558Srgrimes return (1); 11034266Sjulian resolved = 0; 1111558Srgrimes return (0); 1121558Srgrimes} 1131558Srgrimes 1141558Srgrimes/* 11541474Sjulian * Look up state information for an inode. 11641474Sjulian */ 11741474Sjulianstruct inostat * 11841474Sjulianinoinfo(inum) 11941474Sjulian ino_t inum; 12041474Sjulian{ 12141474Sjulian static struct inostat unallocated = { USTATE, 0, 0 }; 12241474Sjulian struct inostatlist *ilp; 12341474Sjulian int iloff; 12441474Sjulian 12541474Sjulian if (inum > maxino) 12641474Sjulian errx(EEXIT, "inoinfo: inumber %d out of range", inum); 12741474Sjulian ilp = &inostathead[inum / sblock.fs_ipg]; 12841474Sjulian iloff = inum % sblock.fs_ipg; 12941474Sjulian if (iloff >= ilp->il_numalloced) 13041474Sjulian return (&unallocated); 13141474Sjulian return (&ilp->il_stat[iloff]); 13241474Sjulian} 13341474Sjulian 13441474Sjulian/* 1351558Srgrimes * Malloc buffers and set up cache. 1361558Srgrimes */ 1377585Sbdevoid 1381558Srgrimesbufinit() 1391558Srgrimes{ 1401558Srgrimes register struct bufarea *bp; 1411558Srgrimes long bufcnt, i; 1421558Srgrimes char *bufp; 1431558Srgrimes 1441558Srgrimes pbp = pdirbp = (struct bufarea *)0; 1451558Srgrimes bufp = malloc((unsigned int)sblock.fs_bsize); 1461558Srgrimes if (bufp == 0) 14723675Speter errx(EEXIT, "cannot allocate buffer pool"); 1481558Srgrimes cgblk.b_un.b_buf = bufp; 1491558Srgrimes initbarea(&cgblk); 1501558Srgrimes bufhead.b_next = bufhead.b_prev = &bufhead; 1511558Srgrimes bufcnt = MAXBUFSPACE / sblock.fs_bsize; 1521558Srgrimes if (bufcnt < MINBUFS) 1531558Srgrimes bufcnt = MINBUFS; 1541558Srgrimes for (i = 0; i < bufcnt; i++) { 1551558Srgrimes bp = (struct bufarea *)malloc(sizeof(struct bufarea)); 1561558Srgrimes bufp = malloc((unsigned int)sblock.fs_bsize); 1571558Srgrimes if (bp == NULL || bufp == NULL) { 1581558Srgrimes if (i >= MINBUFS) 1591558Srgrimes break; 16023675Speter errx(EEXIT, "cannot allocate buffer pool"); 1611558Srgrimes } 1621558Srgrimes bp->b_un.b_buf = bufp; 1631558Srgrimes bp->b_prev = &bufhead; 1641558Srgrimes bp->b_next = bufhead.b_next; 1651558Srgrimes bufhead.b_next->b_prev = bp; 1661558Srgrimes bufhead.b_next = bp; 1671558Srgrimes initbarea(bp); 1681558Srgrimes } 1691558Srgrimes bufhead.b_size = i; /* save number of buffers */ 1701558Srgrimes} 1711558Srgrimes 1721558Srgrimes/* 1731558Srgrimes * Manage a cache of directory blocks. 1741558Srgrimes */ 1751558Srgrimesstruct bufarea * 1761558Srgrimesgetdatablk(blkno, size) 17723675Speter ufs_daddr_t blkno; 1781558Srgrimes long size; 1791558Srgrimes{ 1801558Srgrimes register struct bufarea *bp; 1811558Srgrimes 1821558Srgrimes for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next) 1831558Srgrimes if (bp->b_bno == fsbtodb(&sblock, blkno)) 1841558Srgrimes goto foundit; 1851558Srgrimes for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev) 1861558Srgrimes if ((bp->b_flags & B_INUSE) == 0) 1871558Srgrimes break; 1881558Srgrimes if (bp == &bufhead) 18923675Speter errx(EEXIT, "deadlocked buffer pool"); 1901558Srgrimes getblk(bp, blkno, size); 1911558Srgrimes /* fall through */ 1921558Srgrimesfoundit: 1931558Srgrimes totalreads++; 1941558Srgrimes bp->b_prev->b_next = bp->b_next; 1951558Srgrimes bp->b_next->b_prev = bp->b_prev; 1961558Srgrimes bp->b_prev = &bufhead; 1971558Srgrimes bp->b_next = bufhead.b_next; 1981558Srgrimes bufhead.b_next->b_prev = bp; 1991558Srgrimes bufhead.b_next = bp; 2001558Srgrimes bp->b_flags |= B_INUSE; 2011558Srgrimes return (bp); 2021558Srgrimes} 2031558Srgrimes 2041558Srgrimesvoid 2051558Srgrimesgetblk(bp, blk, size) 2061558Srgrimes register struct bufarea *bp; 20723675Speter ufs_daddr_t blk; 2081558Srgrimes long size; 2091558Srgrimes{ 21023675Speter ufs_daddr_t dblk; 2111558Srgrimes 2121558Srgrimes dblk = fsbtodb(&sblock, blk); 2131558Srgrimes if (bp->b_bno != dblk) { 2141558Srgrimes flush(fswritefd, bp); 2151558Srgrimes diskreads++; 2161558Srgrimes bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, dblk, size); 2171558Srgrimes bp->b_bno = dblk; 2181558Srgrimes bp->b_size = size; 2191558Srgrimes } 2201558Srgrimes} 2211558Srgrimes 2227585Sbdevoid 2231558Srgrimesflush(fd, bp) 2241558Srgrimes int fd; 2251558Srgrimes register struct bufarea *bp; 2261558Srgrimes{ 2271558Srgrimes register int i, j; 2281558Srgrimes 2291558Srgrimes if (!bp->b_dirty) 2301558Srgrimes return; 2311558Srgrimes if (bp->b_errs != 0) 2321558Srgrimes pfatal("WRITING %sZERO'ED BLOCK %d TO DISK\n", 2331558Srgrimes (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ", 2341558Srgrimes bp->b_bno); 2351558Srgrimes bp->b_dirty = 0; 2361558Srgrimes bp->b_errs = 0; 2371558Srgrimes bwrite(fd, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size); 2381558Srgrimes if (bp != &sblk) 2391558Srgrimes return; 2401558Srgrimes for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 2411558Srgrimes bwrite(fswritefd, (char *)sblock.fs_csp[j], 2421558Srgrimes fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), 2431558Srgrimes sblock.fs_cssize - i < sblock.fs_bsize ? 2441558Srgrimes sblock.fs_cssize - i : sblock.fs_bsize); 2451558Srgrimes } 2461558Srgrimes} 2471558Srgrimes 24823675Speterstatic void 2491558Srgrimesrwerror(mesg, blk) 2501558Srgrimes char *mesg; 25123675Speter ufs_daddr_t blk; 2521558Srgrimes{ 2531558Srgrimes 2541558Srgrimes if (preen == 0) 2551558Srgrimes printf("\n"); 2561558Srgrimes pfatal("CANNOT %s: BLK %ld", mesg, blk); 2571558Srgrimes if (reply("CONTINUE") == 0) 25823675Speter exit(EEXIT); 2591558Srgrimes} 2601558Srgrimes 2617585Sbdevoid 26223675Speterckfini(markclean) 26323675Speter int markclean; 2641558Srgrimes{ 2651558Srgrimes register struct bufarea *bp, *nbp; 26623675Speter int ofsmodified, cnt = 0; 2671558Srgrimes 2681558Srgrimes if (fswritefd < 0) { 2691558Srgrimes (void)close(fsreadfd); 2701558Srgrimes return; 2711558Srgrimes } 2721558Srgrimes flush(fswritefd, &sblk); 2731558Srgrimes if (havesb && sblk.b_bno != SBOFF / dev_bsize && 2741558Srgrimes !preen && reply("UPDATE STANDARD SUPERBLOCK")) { 2751558Srgrimes sblk.b_bno = SBOFF / dev_bsize; 2761558Srgrimes sbdirty(); 2771558Srgrimes flush(fswritefd, &sblk); 2781558Srgrimes } 2791558Srgrimes flush(fswritefd, &cgblk); 2801558Srgrimes free(cgblk.b_un.b_buf); 2811558Srgrimes for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) { 2821558Srgrimes cnt++; 2831558Srgrimes flush(fswritefd, bp); 2841558Srgrimes nbp = bp->b_prev; 2851558Srgrimes free(bp->b_un.b_buf); 2861558Srgrimes free((char *)bp); 2871558Srgrimes } 2881558Srgrimes if (bufhead.b_size != cnt) 28941474Sjulian errx(EEXIT, "Panic: lost %d buffers", bufhead.b_size - cnt); 2901558Srgrimes pbp = pdirbp = (struct bufarea *)0; 29141474Sjulian if (sblock.fs_clean != markclean) { 29241474Sjulian sblock.fs_clean = markclean; 29323675Speter sbdirty(); 29423675Speter ofsmodified = fsmodified; 29523675Speter flush(fswritefd, &sblk); 29623675Speter fsmodified = ofsmodified; 29741474Sjulian if (!preen) { 29841474Sjulian printf("\n***** FILE SYSTEM MARKED %s *****\n", 29941474Sjulian markclean ? "CLEAN" : "DIRTY"); 30041474Sjulian if (!markclean) 30141474Sjulian rerun = 1; 30241474Sjulian } 30341474Sjulian } else if (!preen && !markclean) { 30441474Sjulian printf("\n***** FILE SYSTEM STILL DIRTY *****\n"); 30541474Sjulian rerun = 1; 30623675Speter } 3071558Srgrimes if (debug) 3081558Srgrimes printf("cache missed %ld of %ld (%d%%)\n", diskreads, 3091558Srgrimes totalreads, (int)(diskreads * 100 / totalreads)); 3101558Srgrimes (void)close(fsreadfd); 3111558Srgrimes (void)close(fswritefd); 3121558Srgrimes} 3131558Srgrimes 3147585Sbdeint 3151558Srgrimesbread(fd, buf, blk, size) 3161558Srgrimes int fd; 3171558Srgrimes char *buf; 31823675Speter ufs_daddr_t blk; 3191558Srgrimes long size; 3201558Srgrimes{ 3211558Srgrimes char *cp; 3221558Srgrimes int i, errs; 3231558Srgrimes off_t offset; 3241558Srgrimes 3251558Srgrimes offset = blk; 3261558Srgrimes offset *= dev_bsize; 3271558Srgrimes if (lseek(fd, offset, 0) < 0) 3281558Srgrimes rwerror("SEEK", blk); 3291558Srgrimes else if (read(fd, buf, (int)size) == size) 3301558Srgrimes return (0); 3311558Srgrimes rwerror("READ", blk); 3321558Srgrimes if (lseek(fd, offset, 0) < 0) 3331558Srgrimes rwerror("SEEK", blk); 3341558Srgrimes errs = 0; 33523675Speter memset(buf, 0, (size_t)size); 3361558Srgrimes printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:"); 3371558Srgrimes for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) { 3381558Srgrimes if (read(fd, cp, (int)secsize) != secsize) { 3391558Srgrimes (void)lseek(fd, offset + i + secsize, 0); 3401558Srgrimes if (secsize != dev_bsize && dev_bsize != 1) 3411558Srgrimes printf(" %ld (%ld),", 3421558Srgrimes (blk * dev_bsize + i) / secsize, 3431558Srgrimes blk + i / dev_bsize); 3441558Srgrimes else 3451558Srgrimes printf(" %ld,", blk + i / dev_bsize); 3461558Srgrimes errs++; 3471558Srgrimes } 3481558Srgrimes } 3491558Srgrimes printf("\n"); 35041474Sjulian if (errs) 35141474Sjulian resolved = 0; 3521558Srgrimes return (errs); 3531558Srgrimes} 3541558Srgrimes 3557585Sbdevoid 3561558Srgrimesbwrite(fd, buf, blk, size) 3571558Srgrimes int fd; 3581558Srgrimes char *buf; 35923675Speter ufs_daddr_t blk; 3601558Srgrimes long size; 3611558Srgrimes{ 3621558Srgrimes int i; 3631558Srgrimes char *cp; 3641558Srgrimes off_t offset; 3651558Srgrimes 3661558Srgrimes if (fd < 0) 3671558Srgrimes return; 3681558Srgrimes offset = blk; 3691558Srgrimes offset *= dev_bsize; 3701558Srgrimes if (lseek(fd, offset, 0) < 0) 3711558Srgrimes rwerror("SEEK", blk); 3721558Srgrimes else if (write(fd, buf, (int)size) == size) { 3731558Srgrimes fsmodified = 1; 3741558Srgrimes return; 3751558Srgrimes } 37641474Sjulian resolved = 0; 3771558Srgrimes rwerror("WRITE", blk); 3781558Srgrimes if (lseek(fd, offset, 0) < 0) 3791558Srgrimes rwerror("SEEK", blk); 3801558Srgrimes printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:"); 3811558Srgrimes for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize) 3821558Srgrimes if (write(fd, cp, (int)dev_bsize) != dev_bsize) { 3831558Srgrimes (void)lseek(fd, offset + i + dev_bsize, 0); 3841558Srgrimes printf(" %ld,", blk + i / dev_bsize); 3851558Srgrimes } 3861558Srgrimes printf("\n"); 3871558Srgrimes return; 3881558Srgrimes} 3891558Srgrimes 3901558Srgrimes/* 3911558Srgrimes * allocate a data block with the specified number of fragments 3921558Srgrimes */ 39323675Speterufs_daddr_t 3941558Srgrimesallocblk(frags) 3951558Srgrimes long frags; 3961558Srgrimes{ 39734266Sjulian int i, j, k, cg, baseblk; 39834266Sjulian struct cg *cgp = &cgrp; 3991558Srgrimes 4001558Srgrimes if (frags <= 0 || frags > sblock.fs_frag) 4011558Srgrimes return (0); 4021558Srgrimes for (i = 0; i < maxfsblock - sblock.fs_frag; i += sblock.fs_frag) { 4031558Srgrimes for (j = 0; j <= sblock.fs_frag - frags; j++) { 4041558Srgrimes if (testbmap(i + j)) 4051558Srgrimes continue; 4061558Srgrimes for (k = 1; k < frags; k++) 4071558Srgrimes if (testbmap(i + j + k)) 4081558Srgrimes break; 4091558Srgrimes if (k < frags) { 4101558Srgrimes j += k; 4111558Srgrimes continue; 4121558Srgrimes } 41334266Sjulian cg = dtog(&sblock, i + j); 41434266Sjulian getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize); 41534266Sjulian if (!cg_chkmagic(cgp)) 41634266Sjulian pfatal("CG %d: BAD MAGIC NUMBER\n", cg); 41734266Sjulian baseblk = dtogd(&sblock, i + j); 41834266Sjulian for (k = 0; k < frags; k++) { 4191558Srgrimes setbmap(i + j + k); 42034266Sjulian clrbit(cg_blksfree(cgp), baseblk + k); 42134266Sjulian } 4221558Srgrimes n_blks += frags; 42334266Sjulian if (frags == sblock.fs_frag) 42434266Sjulian cgp->cg_cs.cs_nbfree--; 42534266Sjulian else 42634266Sjulian cgp->cg_cs.cs_nffree -= frags; 42734266Sjulian cgdirty(); 4281558Srgrimes return (i + j); 4291558Srgrimes } 4301558Srgrimes } 4311558Srgrimes return (0); 4321558Srgrimes} 4331558Srgrimes 4341558Srgrimes/* 4351558Srgrimes * Free a previously allocated block 4361558Srgrimes */ 4377585Sbdevoid 4381558Srgrimesfreeblk(blkno, frags) 43923675Speter ufs_daddr_t blkno; 4401558Srgrimes long frags; 4411558Srgrimes{ 4421558Srgrimes struct inodesc idesc; 4431558Srgrimes 4441558Srgrimes idesc.id_blkno = blkno; 4451558Srgrimes idesc.id_numfrags = frags; 4461558Srgrimes (void)pass4check(&idesc); 4471558Srgrimes} 4481558Srgrimes 4491558Srgrimes/* 4501558Srgrimes * Find a pathname 4511558Srgrimes */ 4527585Sbdevoid 4531558Srgrimesgetpathname(namebuf, curdir, ino) 4541558Srgrimes char *namebuf; 4551558Srgrimes ino_t curdir, ino; 4561558Srgrimes{ 4571558Srgrimes int len; 4581558Srgrimes register char *cp; 4591558Srgrimes struct inodesc idesc; 4601558Srgrimes static int busy = 0; 4611558Srgrimes 4621558Srgrimes if (curdir == ino && ino == ROOTINO) { 4631558Srgrimes (void)strcpy(namebuf, "/"); 4641558Srgrimes return; 4651558Srgrimes } 4661558Srgrimes if (busy || 46741474Sjulian (inoinfo(curdir)->ino_state != DSTATE && 46841474Sjulian inoinfo(curdir)->ino_state != DFOUND)) { 4691558Srgrimes (void)strcpy(namebuf, "?"); 4701558Srgrimes return; 4711558Srgrimes } 4721558Srgrimes busy = 1; 47323675Speter memset(&idesc, 0, sizeof(struct inodesc)); 4741558Srgrimes idesc.id_type = DATA; 4751558Srgrimes idesc.id_fix = IGNORE; 4761558Srgrimes cp = &namebuf[MAXPATHLEN - 1]; 4771558Srgrimes *cp = '\0'; 4781558Srgrimes if (curdir != ino) { 4791558Srgrimes idesc.id_parent = curdir; 4801558Srgrimes goto namelookup; 4811558Srgrimes } 4821558Srgrimes while (ino != ROOTINO) { 4831558Srgrimes idesc.id_number = ino; 4841558Srgrimes idesc.id_func = findino; 4851558Srgrimes idesc.id_name = ".."; 4861558Srgrimes if ((ckinode(ginode(ino), &idesc) & FOUND) == 0) 4871558Srgrimes break; 4881558Srgrimes namelookup: 4891558Srgrimes idesc.id_number = idesc.id_parent; 4901558Srgrimes idesc.id_parent = ino; 4911558Srgrimes idesc.id_func = findname; 4921558Srgrimes idesc.id_name = namebuf; 4931558Srgrimes if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0) 4941558Srgrimes break; 4951558Srgrimes len = strlen(namebuf); 4961558Srgrimes cp -= len; 49723675Speter memmove(cp, namebuf, (size_t)len); 4981558Srgrimes *--cp = '/'; 4991558Srgrimes if (cp < &namebuf[MAXNAMLEN]) 5001558Srgrimes break; 5011558Srgrimes ino = idesc.id_number; 5021558Srgrimes } 5031558Srgrimes busy = 0; 5041558Srgrimes if (ino != ROOTINO) 5051558Srgrimes *--cp = '?'; 50623675Speter memmove(namebuf, cp, (size_t)(&namebuf[MAXPATHLEN] - cp)); 5071558Srgrimes} 5081558Srgrimes 5091558Srgrimesvoid 51023675Spetercatch(sig) 51123675Speter int sig; 5121558Srgrimes{ 5131558Srgrimes if (!doinglevel2) 51423675Speter ckfini(0); 5151558Srgrimes exit(12); 5161558Srgrimes} 5171558Srgrimes 5181558Srgrimes/* 5191558Srgrimes * When preening, allow a single quit to signal 5201558Srgrimes * a special exit after filesystem checks complete 5211558Srgrimes * so that reboot sequence may be interrupted. 5221558Srgrimes */ 5231558Srgrimesvoid 52423675Spetercatchquit(sig) 52523675Speter int sig; 5261558Srgrimes{ 52741474Sjulian 5281558Srgrimes printf("returning to single-user after filesystem check\n"); 5291558Srgrimes returntosingle = 1; 5301558Srgrimes (void)signal(SIGQUIT, SIG_DFL); 5311558Srgrimes} 5321558Srgrimes 5331558Srgrimes/* 5341558Srgrimes * Ignore a single quit signal; wait and flush just in case. 5351558Srgrimes * Used by child processes in preen. 5361558Srgrimes */ 5371558Srgrimesvoid 53823675Spetervoidquit(sig) 53923675Speter int sig; 5401558Srgrimes{ 5411558Srgrimes 5421558Srgrimes sleep(1); 5431558Srgrimes (void)signal(SIGQUIT, SIG_IGN); 5441558Srgrimes (void)signal(SIGQUIT, SIG_DFL); 5451558Srgrimes} 5461558Srgrimes 5471558Srgrimes/* 5481558Srgrimes * determine whether an inode should be fixed. 5491558Srgrimes */ 5507585Sbdeint 5511558Srgrimesdofix(idesc, msg) 5521558Srgrimes register struct inodesc *idesc; 5531558Srgrimes char *msg; 5541558Srgrimes{ 5551558Srgrimes 5561558Srgrimes switch (idesc->id_fix) { 5571558Srgrimes 5581558Srgrimes case DONTKNOW: 5591558Srgrimes if (idesc->id_type == DATA) 5601558Srgrimes direrror(idesc->id_number, msg); 5611558Srgrimes else 5621558Srgrimes pwarn(msg); 5631558Srgrimes if (preen) { 5641558Srgrimes printf(" (SALVAGED)\n"); 5651558Srgrimes idesc->id_fix = FIX; 5661558Srgrimes return (ALTERED); 5671558Srgrimes } 5681558Srgrimes if (reply("SALVAGE") == 0) { 5691558Srgrimes idesc->id_fix = NOFIX; 5701558Srgrimes return (0); 5711558Srgrimes } 5721558Srgrimes idesc->id_fix = FIX; 5731558Srgrimes return (ALTERED); 5741558Srgrimes 5751558Srgrimes case FIX: 5761558Srgrimes return (ALTERED); 5771558Srgrimes 5781558Srgrimes case NOFIX: 5791558Srgrimes case IGNORE: 5801558Srgrimes return (0); 5811558Srgrimes 5821558Srgrimes default: 58323675Speter errx(EEXIT, "UNKNOWN INODESC FIX MODE %d", idesc->id_fix); 5841558Srgrimes } 5851558Srgrimes /* NOTREACHED */ 58623675Speter return (0); 5871558Srgrimes} 5881558Srgrimes 58923675Speter#if __STDC__ 59023675Speter#include <stdarg.h> 59123675Speter#else 59223675Speter#include <varargs.h> 59323675Speter#endif 5941558Srgrimes 5951558Srgrimes/* 5961558Srgrimes * An unexpected inconsistency occured. 59734266Sjulian * Die if preening or filesystem is running with soft dependency protocol, 59834266Sjulian * otherwise just print message and continue. 5991558Srgrimes */ 6007585Sbdevoid 60123675Speter#if __STDC__ 60223675Speterpfatal(const char *fmt, ...) 60323675Speter#else 60423675Speterpfatal(fmt, va_alist) 60523675Speter char *fmt; 60623675Speter va_dcl 60723675Speter#endif 6081558Srgrimes{ 6097585Sbde va_list ap; 61023675Speter#if __STDC__ 61123675Speter va_start(ap, fmt); 61223675Speter#else 61323675Speter va_start(ap); 61423675Speter#endif 61523675Speter if (!preen) { 61623675Speter (void)vfprintf(stderr, fmt, ap); 61723675Speter va_end(ap); 61834266Sjulian if (usedsoftdep) 61934266Sjulian (void)fprintf(stderr, 62041474Sjulian "\nUNEXPECTED SOFT UPDATE INCONSISTENCY\n"); 62123675Speter return; 6221558Srgrimes } 62341474Sjulian if (cdevname == NULL) 62441474Sjulian cdevname = "fsck"; 62523675Speter (void)fprintf(stderr, "%s: ", cdevname); 62623675Speter (void)vfprintf(stderr, fmt, ap); 62723675Speter (void)fprintf(stderr, 62834266Sjulian "\n%s: UNEXPECTED%sINCONSISTENCY; RUN fsck MANUALLY.\n", 62941474Sjulian cdevname, usedsoftdep ? " SOFT UPDATE " : " "); 63034266Sjulian ckfini(0); 63123675Speter exit(EEXIT); 6321558Srgrimes} 6331558Srgrimes 6341558Srgrimes/* 63534266Sjulian * Pwarn just prints a message when not preening or running soft dependency 63634266Sjulian * protocol, or a warning (preceded by filename) when preening. 6371558Srgrimes */ 6387585Sbdevoid 63923675Speter#if __STDC__ 64023675Speterpwarn(const char *fmt, ...) 64123675Speter#else 64223675Speterpwarn(fmt, va_alist) 64323675Speter char *fmt; 64423675Speter va_dcl 64523675Speter#endif 6461558Srgrimes{ 6477585Sbde va_list ap; 64823675Speter#if __STDC__ 64923675Speter va_start(ap, fmt); 65023675Speter#else 65123675Speter va_start(ap); 65223675Speter#endif 6531558Srgrimes if (preen) 65423675Speter (void)fprintf(stderr, "%s: ", cdevname); 65523675Speter (void)vfprintf(stderr, fmt, ap); 6567585Sbde va_end(ap); 6571558Srgrimes} 6581558Srgrimes 6591558Srgrimes/* 6601558Srgrimes * Stub for routines from kernel. 6611558Srgrimes */ 66218286Sbdevoid 66323675Speter#if __STDC__ 6647585Sbdepanic(const char *fmt, ...) 6657585Sbde#else 6667585Sbdepanic(fmt, va_alist) 6677585Sbde char *fmt; 66823675Speter va_dcl 6697585Sbde#endif 6701558Srgrimes{ 67123675Speter va_list ap; 67223675Speter#if __STDC__ 67323675Speter va_start(ap, fmt); 67423675Speter#else 67523675Speter va_start(ap); 67623675Speter#endif 6771558Srgrimes pfatal("INTERNAL INCONSISTENCY:"); 67823675Speter (void)vfprintf(stderr, fmt, ap); 67923675Speter va_end(ap); 68023675Speter exit(EEXIT); 6811558Srgrimes} 682