fsutil.c revision 86514
148104Syokota/* 248104Syokota * Copyright (c) 1980, 1986, 1993 348104Syokota * The Regents of the University of California. All rights reserved. 448104Syokota * 548104Syokota * Redistribution and use in source and binary forms, with or without 648104Syokota * modification, are permitted provided that the following conditions 748104Syokota * are met: 848104Syokota * 1. Redistributions of source code must retain the above copyright 948104Syokota * notice, this list of conditions and the following disclaimer. 1048104Syokota * 2. Redistributions in binary form must reproduce the above copyright 1148104Syokota * notice, this list of conditions and the following disclaimer in the 1248104Syokota * documentation and/or other materials provided with the distribution. 1348104Syokota * 3. All advertising materials mentioning features or use of this software 1448104Syokota * must display the following acknowledgement: 1548104Syokota * This product includes software developed by the University of 1648104Syokota * California, Berkeley and its contributors. 1748104Syokota * 4. Neither the name of the University nor the names of its contributors 1848104Syokota * may be used to endorse or promote products derived from this software 1948104Syokota * without specific prior written permission. 2048104Syokota * 2148104Syokota * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2248104Syokota * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2348104Syokota * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2448104Syokota * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2548104Syokota * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2648104Syokota * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27119420Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28119420Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29119420Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3048104Syokota * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3148104Syokota * SUCH DAMAGE. 3248104Syokota */ 3348104Syokota 3448104Syokota#ifndef lint 3576166Smarkm#if 0 3676166Smarkmstatic const char sccsid[] = "@(#)utilities.c 8.6 (Berkeley) 5/19/95"; 37114216Skan#endif 3876166Smarkmstatic const char rcsid[] = 3976166Smarkm "$FreeBSD: head/sbin/fsck_ffs/fsutil.c 86514 2001-11-17 23:48:21Z iedowse $"; 4076166Smarkm#endif /* not lint */ 4176166Smarkm 4248104Syokota#include <sys/param.h> 4365690Smarkm#include <sys/types.h> 4476166Smarkm#include <sys/sysctl.h> 4548104Syokota#include <sys/stat.h> 4648104Syokota 4748104Syokota#include <ufs/ufs/dinode.h> 4848104Syokota#include <ufs/ufs/dir.h> 4953011Syokota#include <ufs/ffs/fs.h> 5053011Syokota 5153011Syokota#include <err.h> 5253011Syokota#include <errno.h> 5353011Syokota#include <string.h> 5453011Syokota#include <ctype.h> 5553011Syokota#include <fstab.h> 5653011Syokota#include <stdio.h> 5748104Syokota#include <stdlib.h> 5848104Syokota#include <unistd.h> 5948104Syokota 6048104Syokota#include "fsck.h" 6148104Syokota 6248104Syokotalong diskreads, totalreads; /* Disk cache statistics */ 6348104Syokota 6448104Syokotaint 6548104Syokotaftypeok(dp) 6648104Syokota struct dinode *dp; 6748104Syokota{ 6848104Syokota switch (dp->di_mode & IFMT) { 6948104Syokota 7048104Syokota case IFDIR: 7148104Syokota case IFREG: 7248104Syokota case IFBLK: 7348104Syokota case IFCHR: 7448104Syokota case IFLNK: 7548104Syokota case IFSOCK: 7656043Syokota case IFIFO: 7756043Syokota return (1); 7848104Syokota 79115595Sjmallett default: 8048104Syokota if (debug) 8148104Syokota printf("bad file type 0%o\n", dp->di_mode); 82115595Sjmallett return (0); 8348104Syokota } 8448104Syokota} 8548104Syokota 8648104Syokotaint 8748104Syokotareply(question) 8848104Syokota char *question; 8948104Syokota{ 9048104Syokota int persevere; 9148104Syokota char c; 9248104Syokota 9348104Syokota if (preen) 9448104Syokota pfatal("INTERNAL ERROR: GOT TO reply()"); 9548104Syokota persevere = !strcmp(question, "CONTINUE"); 9648104Syokota printf("\n"); 9748104Syokota if (!persevere && (nflag || (fswritefd < 0 && bkgrdflag == 0))) { 9848104Syokota printf("%s? no\n\n", question); 9948104Syokota resolved = 0; 10048104Syokota return (0); 10148104Syokota } 10248104Syokota if (yflag || (persevere && nflag)) { 10348104Syokota printf("%s? yes\n\n", question); 10448104Syokota return (1); 10548104Syokota } 10648104Syokota do { 10748104Syokota printf("%s? [yn] ", question); 10848104Syokota (void) fflush(stdout); 10948104Syokota c = getc(stdin); 11048104Syokota while (c != '\n' && getc(stdin) != '\n') { 11148104Syokota if (feof(stdin)) { 112111119Simp resolved = 0; 11348104Syokota return (0); 11448104Syokota } 11548104Syokota } 11648104Syokota } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N'); 11748104Syokota printf("\n"); 11848104Syokota if (c == 'y' || c == 'Y') 11948104Syokota return (1); 120197539Sed resolved = 0; 121197539Sed return (0); 122197539Sed} 123197539Sed 124197539Sed/* 125197539Sed * Look up state information for an inode. 126197539Sed */ 127197539Sedstruct inostat * 128197539Sedinoinfo(inum) 129197539Sed ino_t inum; 130197539Sed{ 131197539Sed static struct inostat unallocated = { USTATE, 0, 0 }; 132197539Sed struct inostatlist *ilp; 133197539Sed int iloff; 134197539Sed 135197539Sed if (inum > maxino) 136197539Sed errx(EEXIT, "inoinfo: inumber %d out of range", inum); 137197539Sed ilp = &inostathead[inum / sblock.fs_ipg]; 138197539Sed iloff = inum % sblock.fs_ipg; 139197539Sed if (iloff >= ilp->il_numalloced) 140197539Sed return (&unallocated); 141197539Sed return (&ilp->il_stat[iloff]); 142197539Sed} 143197539Sed 144197539Sed/* 145197539Sed * Malloc buffers and set up cache. 146197539Sed */ 147197539Sedvoid 148197539Sedbufinit() 149197539Sed{ 150197539Sed register struct bufarea *bp; 151197539Sed long bufcnt, i; 152197539Sed char *bufp; 153197539Sed 154197539Sed pbp = pdirbp = (struct bufarea *)0; 155197539Sed bufp = malloc((unsigned int)sblock.fs_bsize); 156197539Sed if (bufp == 0) 157197539Sed errx(EEXIT, "cannot allocate buffer pool"); 158197539Sed cgblk.b_un.b_buf = bufp; 159197539Sed initbarea(&cgblk); 160197539Sed bufhead.b_next = bufhead.b_prev = &bufhead; 161197539Sed bufcnt = MAXBUFSPACE / sblock.fs_bsize; 16248104Syokota if (bufcnt < MINBUFS) 16348104Syokota bufcnt = MINBUFS; 16448104Syokota for (i = 0; i < bufcnt; i++) { 16548104Syokota bp = (struct bufarea *)malloc(sizeof(struct bufarea)); 16648104Syokota bufp = malloc((unsigned int)sblock.fs_bsize); 16748104Syokota if (bp == NULL || bufp == NULL) { 16848104Syokota if (i >= MINBUFS) 16958872Syokota break; 17058872Syokota errx(EEXIT, "cannot allocate buffer pool"); 171149640Srodrigc } 17256528Syokota bp->b_un.b_buf = bufp; 17356528Syokota bp->b_prev = &bufhead; 17456528Syokota bp->b_next = bufhead.b_next; 175119388Sjake bufhead.b_next->b_prev = bp; 176119388Sjake bufhead.b_next = bp; 17758872Syokota initbarea(bp); 17848104Syokota } 17948104Syokota bufhead.b_size = i; /* save number of buffers */ 18048104Syokota} 18148104Syokota 18248104Syokota/* 18348104Syokota * Manage a cache of directory blocks. 18448104Syokota */ 185119388Sjakestruct bufarea * 186119388Sjakegetdatablk(blkno, size) 18748104Syokota ufs_daddr_t blkno; 18848104Syokota long size; 18948104Syokota{ 19048104Syokota register struct bufarea *bp; 19148104Syokota 19248104Syokota for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next) 19348104Syokota if (bp->b_bno == fsbtodb(&sblock, blkno)) 19448104Syokota goto foundit; 19548104Syokota for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev) 196119388Sjake if ((bp->b_flags & B_INUSE) == 0) 197119388Sjake break; 19848104Syokota if (bp == &bufhead) 19948104Syokota errx(EEXIT, "deadlocked buffer pool"); 20048104Syokota getblk(bp, blkno, size); 20148104Syokota /* fall through */ 202149855Srodrigcfoundit: 203149855Srodrigc totalreads++; 20448104Syokota bp->b_prev->b_next = bp->b_next; 20548104Syokota bp->b_next->b_prev = bp->b_prev; 20648104Syokota bp->b_prev = &bufhead; 207119388Sjake bp->b_next = bufhead.b_next; 20848104Syokota bufhead.b_next->b_prev = bp; 20948104Syokota bufhead.b_next = bp; 21048104Syokota bp->b_flags |= B_INUSE; 21148104Syokota return (bp); 21248104Syokota} 21348104Syokota 21448104Syokotavoid 21548104Syokotagetblk(bp, blk, size) 21648104Syokota register struct bufarea *bp; 21748104Syokota ufs_daddr_t blk; 21848104Syokota long size; 21948104Syokota{ 22048104Syokota ufs_daddr_t dblk; 22148104Syokota 22248104Syokota dblk = fsbtodb(&sblock, blk); 223162285Sscottl if (bp->b_bno != dblk) { 22448104Syokota flush(fswritefd, bp); 22548104Syokota diskreads++; 22658872Syokota bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, dblk, size); 22758872Syokota bp->b_bno = dblk; 22858872Syokota bp->b_size = size; 229162285Sscottl } 23048104Syokota} 23148104Syokota 23248104Syokotavoid 23348104Syokotaflush(fd, bp) 23448104Syokota int fd; 23548104Syokota register struct bufarea *bp; 23648104Syokota{ 23748104Syokota register int i, j; 23848104Syokota 23948104Syokota if (!bp->b_dirty) 24048104Syokota return; 241162285Sscottl bp->b_dirty = 0; 24248104Syokota if (fswritefd < 0) { 243119388Sjake pfatal("WRITING IN READ_ONLY MODE.\n"); 244119388Sjake return; 24548104Syokota } 24648104Syokota if (bp->b_errs != 0) 24748104Syokota pfatal("WRITING %sZERO'ED BLOCK %d TO DISK\n", 24848104Syokota (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ", 24948104Syokota bp->b_bno); 25048104Syokota bp->b_errs = 0; 25148104Syokota bwrite(fd, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size); 25248104Syokota if (bp != &sblk) 25348104Syokota return; 25448104Syokota for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 25548104Syokota bwrite(fswritefd, (char *)sblock.fs_csp + i, 25648104Syokota fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), 25748104Syokota sblock.fs_cssize - i < sblock.fs_bsize ? 25848104Syokota sblock.fs_cssize - i : sblock.fs_bsize); 25948104Syokota } 26048104Syokota} 26158872Syokota 262162285Sscottlvoid 26348104Syokotarwerror(mesg, blk) 26448104Syokota char *mesg; 26548104Syokota ufs_daddr_t blk; 26648104Syokota{ 26748104Syokota 26848104Syokota if (bkgrdcheck) 26948104Syokota exit(EEXIT); 27048104Syokota if (preen == 0) 27148104Syokota printf("\n"); 27248104Syokota pfatal("CANNOT %s: %ld", mesg, (long)blk); 27348104Syokota if (reply("CONTINUE") == 0) 27448104Syokota exit(EEXIT); 27548104Syokota} 27648104Syokota 27748104Syokotavoid 27848104Syokotackfini(markclean) 27948104Syokota int markclean; 28048104Syokota{ 28148104Syokota register struct bufarea *bp, *nbp; 28248104Syokota int ofsmodified, cnt = 0; 28348104Syokota 28448104Syokota if (bkgrdflag) { 28548104Syokota unlink(snapname); 28648104Syokota if ((!(sblock.fs_flags & FS_UNCLEAN)) != markclean) { 28748104Syokota cmd.value = FS_UNCLEAN; 28848104Syokota cmd.size = markclean ? -1 : 1; 28948104Syokota if (sysctlbyname("vfs.ffs.setflags", 0, 0, 29048104Syokota &cmd, sizeof cmd) == -1) 29148104Syokota rwerror("SET FILESYSTEM FLAGS", FS_UNCLEAN); 29248104Syokota if (!preen) { 29348104Syokota printf("\n***** FILE SYSTEM MARKED %s *****\n", 29448104Syokota markclean ? "CLEAN" : "DIRTY"); 29548104Syokota if (!markclean) 29648104Syokota rerun = 1; 29748104Syokota } 29848104Syokota } else if (!preen && !markclean) { 29948104Syokota printf("\n***** FILE SYSTEM STILL DIRTY *****\n"); 30048104Syokota rerun = 1; 30148104Syokota } 30251404Syokota } 30348104Syokota if (fswritefd < 0) { 30448104Syokota (void)close(fsreadfd); 30548104Syokota return; 30648104Syokota } 30751404Syokota flush(fswritefd, &sblk); 30851404Syokota if (havesb && sblk.b_bno != SBOFF / dev_bsize && cursnapshot == 0 && 30948104Syokota !preen && reply("UPDATE STANDARD SUPERBLOCK")) { 31051404Syokota sblk.b_bno = SBOFF / dev_bsize; 31148104Syokota sbdirty(); 31248104Syokota flush(fswritefd, &sblk); 31348104Syokota } 31448104Syokota flush(fswritefd, &cgblk); 31548104Syokota free(cgblk.b_un.b_buf); 31648104Syokota for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) { 31751404Syokota cnt++; 31848104Syokota flush(fswritefd, bp); 31948104Syokota nbp = bp->b_prev; 32048104Syokota free(bp->b_un.b_buf); 32151404Syokota free((char *)bp); 32251404Syokota } 32348104Syokota if (bufhead.b_size != cnt) 32451404Syokota errx(EEXIT, "panic: lost %d buffers", bufhead.b_size - cnt); 32551404Syokota pbp = pdirbp = (struct bufarea *)0; 32651404Syokota if (cursnapshot == 0 && sblock.fs_clean != markclean) { 32748104Syokota if ((sblock.fs_clean = markclean) != 0) 32848104Syokota sblock.fs_flags &= ~(FS_UNCLEAN | FS_NEEDSFSCK); 32948104Syokota sbdirty(); 33048104Syokota ofsmodified = fsmodified; 33152813Sarchie flush(fswritefd, &sblk); 33248104Syokota fsmodified = ofsmodified; 33383791Ssobomax if (!preen) { 33483791Ssobomax printf("\n***** FILE SYSTEM MARKED %s *****\n", 33583791Ssobomax markclean ? "CLEAN" : "DIRTY"); 33683791Ssobomax if (!markclean) 33783791Ssobomax rerun = 1; 33883791Ssobomax } 33983791Ssobomax } else if (!preen && !markclean) { 34083791Ssobomax printf("\n***** FILE SYSTEM STILL DIRTY *****\n"); 34183791Ssobomax rerun = 1; 34283791Ssobomax } 34383791Ssobomax if (debug && totalreads > 0) 34483791Ssobomax printf("cache missed %ld of %ld (%d%%)\n", diskreads, 34548104Syokota totalreads, (int)(diskreads * 100 / totalreads)); 34648104Syokota (void)close(fsreadfd); 34748104Syokota (void)close(fswritefd); 34848104Syokota} 34948104Syokota 35048104Syokotaint 35148104Syokotabread(fd, buf, blk, size) 35248104Syokota int fd; 35348104Syokota char *buf; 35452813Sarchie ufs_daddr_t blk; 35548104Syokota long size; 35648104Syokota{ 35748104Syokota char *cp; 35848104Syokota int i, errs; 35948104Syokota off_t offset; 36048104Syokota 36148104Syokota offset = blk; 36248104Syokota offset *= dev_bsize; 36348104Syokota if (lseek(fd, offset, 0) < 0) 36448104Syokota rwerror("SEEK BLK", blk); 36548104Syokota else if (read(fd, buf, (int)size) == size) 36648104Syokota return (0); 36748104Syokota rwerror("READ BLK", blk); 36848104Syokota if (lseek(fd, offset, 0) < 0) 36948104Syokota rwerror("SEEK BLK", blk); 37052813Sarchie errs = 0; 37148104Syokota memset(buf, 0, (size_t)size); 37248104Syokota printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:"); 37348104Syokota for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) { 37448104Syokota if (read(fd, cp, (int)secsize) != secsize) { 37548104Syokota (void)lseek(fd, offset + i + secsize, 0); 37648104Syokota if (secsize != dev_bsize && dev_bsize != 1) 37783791Ssobomax printf(" %ld (%ld),", 37883791Ssobomax (blk * dev_bsize + i) / secsize, 37983791Ssobomax blk + i / dev_bsize); 38083791Ssobomax else 38183791Ssobomax printf(" %ld,", blk + i / dev_bsize); 38283791Ssobomax errs++; 38383791Ssobomax } 38483791Ssobomax } 38583791Ssobomax printf("\n"); 38683791Ssobomax if (errs) 38783791Ssobomax resolved = 0; 38883791Ssobomax return (errs); 38983791Ssobomax} 39083791Ssobomax 39183791Ssobomaxvoid 39283791Ssobomaxbwrite(fd, buf, blk, size) 39383791Ssobomax int fd; 39483791Ssobomax char *buf; 39583791Ssobomax ufs_daddr_t blk; 39683791Ssobomax long size; 39783791Ssobomax{ 39883791Ssobomax int i; 39983791Ssobomax char *cp; 40083791Ssobomax off_t offset; 40183791Ssobomax 40283791Ssobomax if (fd < 0) 40383791Ssobomax return; 40483791Ssobomax offset = blk; 40583791Ssobomax offset *= dev_bsize; 40683791Ssobomax if (lseek(fd, offset, 0) < 0) 40783791Ssobomax rwerror("SEEK BLK", blk); 40883791Ssobomax else if (write(fd, buf, (int)size) == size) { 40983791Ssobomax fsmodified = 1; 41083791Ssobomax return; 41183791Ssobomax } 41283791Ssobomax resolved = 0; 41383791Ssobomax rwerror("WRITE BLK", blk); 41483791Ssobomax if (lseek(fd, offset, 0) < 0) 41583791Ssobomax rwerror("SEEK BLK", blk); 41683791Ssobomax printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:"); 41783791Ssobomax for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize) 41883791Ssobomax if (write(fd, cp, (int)dev_bsize) != dev_bsize) { 41983791Ssobomax (void)lseek(fd, offset + i + dev_bsize, 0); 42083791Ssobomax printf(" %ld,", blk + i / dev_bsize); 42183791Ssobomax } 42283791Ssobomax printf("\n"); 42383791Ssobomax return; 42483791Ssobomax} 42583791Ssobomax 42683791Ssobomax/* 42783791Ssobomax * allocate a data block with the specified number of fragments 42883791Ssobomax */ 42983791Ssobomaxufs_daddr_t 43083791Ssobomaxallocblk(frags) 43183791Ssobomax long frags; 43283791Ssobomax{ 43383791Ssobomax int i, j, k, cg, baseblk; 43483791Ssobomax struct cg *cgp = &cgrp; 43583791Ssobomax 43683791Ssobomax if (frags <= 0 || frags > sblock.fs_frag) 43748104Syokota return (0); 43848104Syokota for (i = 0; i < maxfsblock - sblock.fs_frag; i += sblock.fs_frag) { 43948104Syokota for (j = 0; j <= sblock.fs_frag - frags; j++) { 44048104Syokota if (testbmap(i + j)) 44148104Syokota continue; 44248104Syokota for (k = 1; k < frags; k++) 44348104Syokota if (testbmap(i + j + k)) 44448104Syokota break; 44548104Syokota if (k < frags) { 44648104Syokota j += k; 44748104Syokota continue; 44848104Syokota } 44948104Syokota cg = dtog(&sblock, i + j); 45048104Syokota getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize); 45148104Syokota if (!cg_chkmagic(cgp)) 45248104Syokota pfatal("CG %d: BAD MAGIC NUMBER\n", cg); 45348104Syokota baseblk = dtogd(&sblock, i + j); 45448104Syokota for (k = 0; k < frags; k++) { 45548104Syokota setbmap(i + j + k); 45648104Syokota clrbit(cg_blksfree(cgp), baseblk + k); 45748104Syokota } 45848104Syokota n_blks += frags; 45983791Ssobomax if (frags == sblock.fs_frag) 46048104Syokota cgp->cg_cs.cs_nbfree--; 46148104Syokota else 46252813Sarchie cgp->cg_cs.cs_nffree -= frags; 46348104Syokota cgdirty(); 46448104Syokota return (i + j); 46548104Syokota } 46648104Syokota } 46783791Ssobomax return (0); 46848104Syokota} 46948104Syokota 47048104Syokota/* 47148104Syokota * Free a previously allocated block 47248104Syokota */ 47383791Ssobomaxvoid 47448104Syokotafreeblk(blkno, frags) 47548104Syokota ufs_daddr_t blkno; 47648104Syokota long frags; 47748104Syokota{ 47848104Syokota struct inodesc idesc; 47948104Syokota 48048104Syokota idesc.id_blkno = blkno; 48148104Syokota idesc.id_numfrags = frags; 48283791Ssobomax (void)pass4check(&idesc); 48348104Syokota} 48448104Syokota 48548104Syokota/* 48648104Syokota * Find a pathname 48748104Syokota */ 48848104Syokotavoid 489169983Sdelphijgetpathname(namebuf, curdir, ino) 490169983Sdelphij char *namebuf; 49148104Syokota ino_t curdir, ino; 49283791Ssobomax{ 49348104Syokota int len; 49448104Syokota register char *cp; 49548104Syokota struct inodesc idesc; 49648104Syokota static int busy = 0; 49748104Syokota 49848104Syokota if (curdir == ino && ino == ROOTINO) { 49948104Syokota (void)strcpy(namebuf, "/"); 50048104Syokota return; 50148104Syokota } 50248104Syokota if (busy || 50348104Syokota (inoinfo(curdir)->ino_state != DSTATE && 50448104Syokota inoinfo(curdir)->ino_state != DFOUND)) { 50548104Syokota (void)strcpy(namebuf, "?"); 50648104Syokota return; 50748104Syokota } 50848104Syokota busy = 1; 50948104Syokota memset(&idesc, 0, sizeof(struct inodesc)); 51083791Ssobomax idesc.id_type = DATA; 51183791Ssobomax idesc.id_fix = IGNORE; 51248104Syokota cp = &namebuf[MAXPATHLEN - 1]; 51348104Syokota *cp = '\0'; 51448104Syokota if (curdir != ino) { 51548104Syokota idesc.id_parent = curdir; 51648104Syokota goto namelookup; 51748104Syokota } 51848104Syokota while (ino != ROOTINO) { 51948104Syokota idesc.id_number = ino; 52048104Syokota idesc.id_func = findino; 52148104Syokota idesc.id_name = ".."; 52248104Syokota if ((ckinode(ginode(ino), &idesc) & FOUND) == 0) 52348104Syokota break; 52448104Syokota namelookup: 52548104Syokota idesc.id_number = idesc.id_parent; 52648104Syokota idesc.id_parent = ino; 52748104Syokota idesc.id_func = findname; 52848104Syokota idesc.id_name = namebuf; 52948104Syokota if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0) 53048104Syokota break; 53148104Syokota len = strlen(namebuf); 53248104Syokota cp -= len; 53348104Syokota memmove(cp, namebuf, (size_t)len); 53488926Ssobomax *--cp = '/'; 53548104Syokota if (cp < &namebuf[MAXNAMLEN]) 53648104Syokota break; 53748104Syokota ino = idesc.id_number; 53848104Syokota } 53983791Ssobomax busy = 0; 54083791Ssobomax if (ino != ROOTINO) 54148104Syokota *--cp = '?'; 54248104Syokota memmove(namebuf, cp, (size_t)(&namebuf[MAXPATHLEN] - cp)); 54348104Syokota} 54448104Syokota 54548104Syokotavoid 54683791Ssobomaxcatch(sig) 54748104Syokota int sig; 54848104Syokota{ 54948104Syokota if (!doinglevel2) 55083791Ssobomax ckfini(0); 55148104Syokota exit(12); 55248104Syokota} 55348104Syokota 55448104Syokota/* 55548104Syokota * When preening, allow a single quit to signal 55683791Ssobomax * a special exit after filesystem checks complete 55748104Syokota * so that reboot sequence may be interrupted. 55848104Syokota */ 55948104Syokotavoid 56048104Syokotacatchquit(sig) 56148104Syokota int sig; 56248104Syokota{ 56348104Syokota printf("returning to single-user after filesystem check\n"); 56483791Ssobomax returntosingle = 1; 56548104Syokota (void)signal(SIGQUIT, SIG_DFL); 56648104Syokota} 56748104Syokota 56848104Syokota/* 56948104Syokota * determine whether an inode should be fixed. 57083791Ssobomax */ 57148104Syokotaint 57248104Syokotadofix(idesc, msg) 57348104Syokota register struct inodesc *idesc; 57448104Syokota char *msg; 57548104Syokota{ 57648104Syokota 57783791Ssobomax switch (idesc->id_fix) { 57888926Ssobomax 57988926Ssobomax case DONTKNOW: 58088926Ssobomax if (idesc->id_type == DATA) 58148104Syokota direrror(idesc->id_number, msg); 58248104Syokota else 58348104Syokota pwarn("%s", msg); 58448104Syokota if (preen) { 58548104Syokota printf(" (SALVAGED)\n"); 58648104Syokota idesc->id_fix = FIX; 58748104Syokota return (ALTERED); 58886894Ssobomax } 58983791Ssobomax if (reply("SALVAGE") == 0) { 59048104Syokota idesc->id_fix = NOFIX; 59148104Syokota return (0); 59283791Ssobomax } 59383791Ssobomax idesc->id_fix = FIX; 59486894Ssobomax return (ALTERED); 59586894Ssobomax 59686894Ssobomax case FIX: 59748104Syokota return (ALTERED); 59848104Syokota 59948104Syokota case NOFIX: 60048104Syokota case IGNORE: 60148104Syokota return (0); 60248104Syokota 60348104Syokota default: 60448104Syokota errx(EEXIT, "UNKNOWN INODESC FIX MODE %d", idesc->id_fix); 60548104Syokota } 60648104Syokota /* NOTREACHED */ 60748104Syokota return (0); 60848104Syokota} 60948104Syokota 61048104Syokota#if __STDC__ 61148104Syokota#include <stdarg.h> 61248104Syokota#else 61348104Syokota#include <varargs.h> 61448104Syokota#endif 61548104Syokota 61648104Syokota/* 61748104Syokota * An unexpected inconsistency occured. 61848104Syokota * Die if preening or filesystem is running with soft dependency protocol, 61948104Syokota * otherwise just print message and continue. 62048104Syokota */ 62148104Syokotavoid 62248104Syokota#if __STDC__ 62348104Syokotapfatal(const char *fmt, ...) 62448104Syokota#else 62548104Syokotapfatal(fmt, va_alist) 62648104Syokota char *fmt; 62748104Syokota va_dcl 62848104Syokota#endif 62948104Syokota{ 63048104Syokota va_list ap; 63148104Syokota#if __STDC__ 63248104Syokota va_start(ap, fmt); 63348104Syokota#else 63448104Syokota va_start(ap); 63548104Syokota#endif 63648104Syokota if (!preen) { 63748104Syokota (void)vfprintf(stdout, fmt, ap); 63848104Syokota va_end(ap); 63948104Syokota if (usedsoftdep) 64048104Syokota (void)fprintf(stdout, 64174118Sache "\nUNEXPECTED SOFT UPDATE INCONSISTENCY\n"); 64274118Sache /* 64348104Syokota * Force foreground fsck to clean up inconsistency. 64474125Sache */ 64548104Syokota if (bkgrdflag) { 64648104Syokota cmd.value = FS_NEEDSFSCK; 64748104Syokota cmd.size = 1; 64848104Syokota if (sysctlbyname("vfs.ffs.setflags", 0, 0, 64948104Syokota &cmd, sizeof cmd) == -1) 650181905Sed pwarn("CANNOT SET FS_NEEDSFSCK FLAG\n"); 65148104Syokota fprintf(stdout, "CANNOT RUN IN BACKGROUND\n"); 65256043Syokota ckfini(0); 65356043Syokota exit(EEXIT); 65456043Syokota } 65548104Syokota return; 65675893Sjhb } 65748104Syokota if (cdevname == NULL) 65856043Syokota cdevname = "fsck"; 65948104Syokota (void)fprintf(stdout, "%s: ", cdevname); 660181905Sed (void)vfprintf(stdout, fmt, ap); 66148104Syokota (void)fprintf(stdout, 66248104Syokota "\n%s: UNEXPECTED%sINCONSISTENCY; RUN fsck MANUALLY.\n", 66348104Syokota cdevname, usedsoftdep ? " SOFT UPDATE " : " "); 66448104Syokota /* 66548104Syokota * Force foreground fsck to clean up inconsistency. 66648104Syokota */ 66756043Syokota if (bkgrdflag) { 66865690Smarkm cmd.value = FS_NEEDSFSCK; 66965690Smarkm cmd.size = 1; 67065690Smarkm if (sysctlbyname("vfs.ffs.setflags", 0, 0, 67148104Syokota &cmd, sizeof cmd) == -1) 67248104Syokota pwarn("CANNOT SET FS_NEEDSFSCK FLAG\n"); 67348104Syokota } 67448104Syokota ckfini(0); 67548104Syokota exit(EEXIT); 67648104Syokota} 67748104Syokota 67848104Syokota/* 67948104Syokota * Pwarn just prints a message when not preening or running soft dependency 68048104Syokota * protocol, or a warning (preceded by filename) when preening. 68148104Syokota */ 68248104Syokotavoid 68348104Syokota#if __STDC__ 68448104Syokotapwarn(const char *fmt, ...) 68548104Syokota#else 68648104Syokotapwarn(fmt, va_alist) 68748104Syokota char *fmt; 68848104Syokota va_dcl 68948104Syokota#endif 69048104Syokota{ 69148104Syokota va_list ap; 69248104Syokota#if __STDC__ 69348104Syokota va_start(ap, fmt); 69448104Syokota#else 69548104Syokota va_start(ap); 69678951Syokota#endif 69748104Syokota if (preen) 69848104Syokota (void)fprintf(stdout, "%s: ", cdevname); 69948104Syokota (void)vfprintf(stdout, fmt, ap); 70048104Syokota va_end(ap); 70148104Syokota} 70248104Syokota 70348104Syokota/* 70448104Syokota * Stub for routines from kernel. 70548104Syokota */ 70648104Syokotavoid 70748104Syokota#if __STDC__ 70883366Sjulianpanic(const char *fmt, ...) 70983366Sjulian#else 71048104Syokotapanic(fmt, va_alist) 71148104Syokota char *fmt; 71248104Syokota va_dcl 71348104Syokota#endif 71448104Syokota{ 71548104Syokota va_list ap; 71648104Syokota#if __STDC__ 71748104Syokota va_start(ap, fmt); 71848104Syokota#else 71948104Syokota va_start(ap); 72048104Syokota#endif 72148104Syokota pfatal("INTERNAL INCONSISTENCY:"); 72258872Syokota (void)vfprintf(stdout, fmt, ap); 72358872Syokota va_end(ap); 72448104Syokota exit(EEXIT); 72548104Syokota} 726146736Sdelphij