1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 8*7c478bd9Sstevel@tonic-gate 9*7c478bd9Sstevel@tonic-gate /* 10*7c478bd9Sstevel@tonic-gate * Copyright (c) 1980, 1986, 1990 The Regents of the University of California. 11*7c478bd9Sstevel@tonic-gate * All rights reserved. 12*7c478bd9Sstevel@tonic-gate * 13*7c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted 14*7c478bd9Sstevel@tonic-gate * provided that: (1) source distributions retain this entire copyright 15*7c478bd9Sstevel@tonic-gate * notice and comment, and (2) distributions including binaries display 16*7c478bd9Sstevel@tonic-gate * the following acknowledgement: ``This product includes software 17*7c478bd9Sstevel@tonic-gate * developed by the University of California, Berkeley and its contributors'' 18*7c478bd9Sstevel@tonic-gate * in the documentation or other materials provided with the distribution 19*7c478bd9Sstevel@tonic-gate * and in all advertising materials mentioning features or use of this 20*7c478bd9Sstevel@tonic-gate * software. Neither the name of the University nor the names of its 21*7c478bd9Sstevel@tonic-gate * contributors may be used to endorse or promote products derived 22*7c478bd9Sstevel@tonic-gate * from this software without specific prior written permission. 23*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 24*7c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 25*7c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 26*7c478bd9Sstevel@tonic-gate */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #include <stdio.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/filio.h> 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate #define bcopy(f, t, n) memcpy(t, f, n) 37*7c478bd9Sstevel@tonic-gate #define bzero(s, n) memset(s, 0, n) 38*7c478bd9Sstevel@tonic-gate #define bcmp(s, d, n) memcmp(s, d, n) 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate #define index(s, r) strchr(s, r) 41*7c478bd9Sstevel@tonic-gate #define rindex(s, r) strrchr(s, r) 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fs.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_inode.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_acl.h> 47*7c478bd9Sstevel@tonic-gate #define _KERNEL 48*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fsdir.h> 49*7c478bd9Sstevel@tonic-gate #undef _KERNEL 50*7c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/signal.h> 54*7c478bd9Sstevel@tonic-gate #include <string.h> 55*7c478bd9Sstevel@tonic-gate #include <ctype.h> 56*7c478bd9Sstevel@tonic-gate #include "fsck.h" 57*7c478bd9Sstevel@tonic-gate #include <sys/vfstab.h> 58*7c478bd9Sstevel@tonic-gate #include <sys/lockfs.h> 59*7c478bd9Sstevel@tonic-gate #include <errno.h> 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate int64_t diskreads, totalreads; /* Disk cache statistics */ 62*7c478bd9Sstevel@tonic-gate offset_t llseek(); 63*7c478bd9Sstevel@tonic-gate char *malloc(); 64*7c478bd9Sstevel@tonic-gate char *mount_point = NULL; 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate extern int mflag; 67*7c478bd9Sstevel@tonic-gate extern uint_t largefile_count; 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate static struct bufarea *alloc_bufarea(); 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate ftypeok(dp) 72*7c478bd9Sstevel@tonic-gate struct dinode *dp; 73*7c478bd9Sstevel@tonic-gate { 74*7c478bd9Sstevel@tonic-gate switch (dp->di_mode & IFMT) { 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate case IFDIR: 77*7c478bd9Sstevel@tonic-gate case IFREG: 78*7c478bd9Sstevel@tonic-gate case IFBLK: 79*7c478bd9Sstevel@tonic-gate case IFCHR: 80*7c478bd9Sstevel@tonic-gate case IFLNK: 81*7c478bd9Sstevel@tonic-gate case IFSOCK: 82*7c478bd9Sstevel@tonic-gate case IFIFO: 83*7c478bd9Sstevel@tonic-gate case IFSHAD: 84*7c478bd9Sstevel@tonic-gate case IFATTRDIR: 85*7c478bd9Sstevel@tonic-gate return (1); 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate default: 88*7c478bd9Sstevel@tonic-gate if (debug) 89*7c478bd9Sstevel@tonic-gate printf("bad file type 0%o\n", dp->di_mode); 90*7c478bd9Sstevel@tonic-gate return (0); 91*7c478bd9Sstevel@tonic-gate } 92*7c478bd9Sstevel@tonic-gate } 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate acltypeok(dp) 95*7c478bd9Sstevel@tonic-gate struct dinode *dp; 96*7c478bd9Sstevel@tonic-gate { 97*7c478bd9Sstevel@tonic-gate if (CHECK_ACL_ALLOWED(dp->di_mode & IFMT)) 98*7c478bd9Sstevel@tonic-gate return (1); 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate if (debug) 101*7c478bd9Sstevel@tonic-gate printf("bad file type for acl 0%o\n", dp->di_mode); 102*7c478bd9Sstevel@tonic-gate return (0); 103*7c478bd9Sstevel@tonic-gate } 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate reply(question) 106*7c478bd9Sstevel@tonic-gate char *question; 107*7c478bd9Sstevel@tonic-gate { 108*7c478bd9Sstevel@tonic-gate char line[80]; 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate if (preen) 111*7c478bd9Sstevel@tonic-gate pfatal("INTERNAL ERROR: GOT TO reply()"); 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate if (mflag) { 114*7c478bd9Sstevel@tonic-gate printf("\n"); 115*7c478bd9Sstevel@tonic-gate printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", 116*7c478bd9Sstevel@tonic-gate devname); 117*7c478bd9Sstevel@tonic-gate exit(39); 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate printf("\n%s? ", question); 121*7c478bd9Sstevel@tonic-gate if (nflag || fswritefd < 0) { 122*7c478bd9Sstevel@tonic-gate printf(" no\n\n"); 123*7c478bd9Sstevel@tonic-gate iscorrupt = 1; /* known to be corrupt */ 124*7c478bd9Sstevel@tonic-gate return (0); 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate if (yflag) { 127*7c478bd9Sstevel@tonic-gate printf(" yes\n\n"); 128*7c478bd9Sstevel@tonic-gate return (1); 129*7c478bd9Sstevel@tonic-gate } 130*7c478bd9Sstevel@tonic-gate if (getline(stdin, line, sizeof (line)) == EOF) 131*7c478bd9Sstevel@tonic-gate errexit("\n"); 132*7c478bd9Sstevel@tonic-gate printf("\n"); 133*7c478bd9Sstevel@tonic-gate if (line[0] == 'y' || line[0] == 'Y') 134*7c478bd9Sstevel@tonic-gate return (1); 135*7c478bd9Sstevel@tonic-gate else { 136*7c478bd9Sstevel@tonic-gate iscorrupt = 1; /* known to be corrupt */ 137*7c478bd9Sstevel@tonic-gate return (0); 138*7c478bd9Sstevel@tonic-gate } 139*7c478bd9Sstevel@tonic-gate } 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate getline(fp, loc, maxlen) 142*7c478bd9Sstevel@tonic-gate FILE *fp; 143*7c478bd9Sstevel@tonic-gate char *loc; 144*7c478bd9Sstevel@tonic-gate { 145*7c478bd9Sstevel@tonic-gate int n; 146*7c478bd9Sstevel@tonic-gate char *p, *lastloc; 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate p = loc; 149*7c478bd9Sstevel@tonic-gate lastloc = &p[maxlen-1]; 150*7c478bd9Sstevel@tonic-gate while ((n = getc(fp)) != '\n') { 151*7c478bd9Sstevel@tonic-gate if (n == EOF) 152*7c478bd9Sstevel@tonic-gate return (EOF); 153*7c478bd9Sstevel@tonic-gate if (!isspace(n) && p < lastloc) 154*7c478bd9Sstevel@tonic-gate *p++ = n; 155*7c478bd9Sstevel@tonic-gate } 156*7c478bd9Sstevel@tonic-gate *p = 0; 157*7c478bd9Sstevel@tonic-gate return (p - loc); 158*7c478bd9Sstevel@tonic-gate } 159*7c478bd9Sstevel@tonic-gate /* 160*7c478bd9Sstevel@tonic-gate * Malloc buffers and set up cache. 161*7c478bd9Sstevel@tonic-gate */ 162*7c478bd9Sstevel@tonic-gate bufinit() 163*7c478bd9Sstevel@tonic-gate { 164*7c478bd9Sstevel@tonic-gate struct bufarea *bp; 165*7c478bd9Sstevel@tonic-gate int bufcnt, i; 166*7c478bd9Sstevel@tonic-gate char *bufp; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate bufp = malloc((unsigned int)sblock.fs_bsize); 169*7c478bd9Sstevel@tonic-gate if (bufp == 0) 170*7c478bd9Sstevel@tonic-gate errexit("cannot allocate buffer pool\n"); 171*7c478bd9Sstevel@tonic-gate cgblk.b_un.b_buf = bufp; 172*7c478bd9Sstevel@tonic-gate initbarea(&cgblk); 173*7c478bd9Sstevel@tonic-gate bufhead.b_next = bufhead.b_prev = &bufhead; 174*7c478bd9Sstevel@tonic-gate bufcnt = MAXBUFSPACE / sblock.fs_bsize; 175*7c478bd9Sstevel@tonic-gate if (bufcnt < MINBUFS) 176*7c478bd9Sstevel@tonic-gate bufcnt = MINBUFS; 177*7c478bd9Sstevel@tonic-gate for (i = 0; i < bufcnt; i++) { 178*7c478bd9Sstevel@tonic-gate bp = (struct bufarea *)malloc(sizeof (struct bufarea)); 179*7c478bd9Sstevel@tonic-gate bufp = malloc((unsigned int)sblock.fs_bsize); 180*7c478bd9Sstevel@tonic-gate if (bp == NULL || bufp == NULL) { 181*7c478bd9Sstevel@tonic-gate if (bp) 182*7c478bd9Sstevel@tonic-gate free((char *)bp); 183*7c478bd9Sstevel@tonic-gate if (bufp) 184*7c478bd9Sstevel@tonic-gate free(bufp); 185*7c478bd9Sstevel@tonic-gate if (i >= MINBUFS) 186*7c478bd9Sstevel@tonic-gate break; 187*7c478bd9Sstevel@tonic-gate errexit("cannot allocate buffer pool\n"); 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate bp->b_un.b_buf = bufp; 190*7c478bd9Sstevel@tonic-gate bp->b_prev = &bufhead; 191*7c478bd9Sstevel@tonic-gate bp->b_next = bufhead.b_next; 192*7c478bd9Sstevel@tonic-gate bufhead.b_next->b_prev = bp; 193*7c478bd9Sstevel@tonic-gate bufhead.b_next = bp; 194*7c478bd9Sstevel@tonic-gate initbarea(bp); 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate bufhead.b_size = i; /* save number of buffers */ 197*7c478bd9Sstevel@tonic-gate pbp = pdirbp = NULL; 198*7c478bd9Sstevel@tonic-gate } 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate /* 201*7c478bd9Sstevel@tonic-gate * Manage a cache of directory blocks. 202*7c478bd9Sstevel@tonic-gate */ 203*7c478bd9Sstevel@tonic-gate struct bufarea * 204*7c478bd9Sstevel@tonic-gate getdatablk(blkno, size) 205*7c478bd9Sstevel@tonic-gate daddr32_t blkno; 206*7c478bd9Sstevel@tonic-gate int size; 207*7c478bd9Sstevel@tonic-gate { 208*7c478bd9Sstevel@tonic-gate struct bufarea *bp; 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next) 211*7c478bd9Sstevel@tonic-gate if (bp->b_bno == fsbtodb(&sblock, blkno)) 212*7c478bd9Sstevel@tonic-gate goto foundit; 213*7c478bd9Sstevel@tonic-gate for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev) 214*7c478bd9Sstevel@tonic-gate if ((bp->b_flags & B_INUSE) == 0) 215*7c478bd9Sstevel@tonic-gate break; 216*7c478bd9Sstevel@tonic-gate if (bp == &bufhead) { 217*7c478bd9Sstevel@tonic-gate bp = alloc_bufarea(); 218*7c478bd9Sstevel@tonic-gate if (bp == NULL) 219*7c478bd9Sstevel@tonic-gate errexit("deadlocked buffer pool\n"); 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate getblk(bp, blkno, size); 222*7c478bd9Sstevel@tonic-gate /* fall through */ 223*7c478bd9Sstevel@tonic-gate foundit: 224*7c478bd9Sstevel@tonic-gate totalreads++; 225*7c478bd9Sstevel@tonic-gate bp->b_cnt++; 226*7c478bd9Sstevel@tonic-gate /* 227*7c478bd9Sstevel@tonic-gate * Move the buffer to head of link-list if it isn't 228*7c478bd9Sstevel@tonic-gate * already there. 229*7c478bd9Sstevel@tonic-gate */ 230*7c478bd9Sstevel@tonic-gate if (bufhead.b_next != bp) { 231*7c478bd9Sstevel@tonic-gate bp->b_prev->b_next = bp->b_next; 232*7c478bd9Sstevel@tonic-gate bp->b_next->b_prev = bp->b_prev; 233*7c478bd9Sstevel@tonic-gate bp->b_prev = &bufhead; 234*7c478bd9Sstevel@tonic-gate bp->b_next = bufhead.b_next; 235*7c478bd9Sstevel@tonic-gate bufhead.b_next->b_prev = bp; 236*7c478bd9Sstevel@tonic-gate bufhead.b_next = bp; 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate bp->b_flags |= B_INUSE; 239*7c478bd9Sstevel@tonic-gate return (bp); 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate int 243*7c478bd9Sstevel@tonic-gate brelse(struct bufarea *bp) 244*7c478bd9Sstevel@tonic-gate { 245*7c478bd9Sstevel@tonic-gate bp->b_cnt--; 246*7c478bd9Sstevel@tonic-gate if (bp->b_cnt == 0) { 247*7c478bd9Sstevel@tonic-gate bp->b_flags &= ~B_INUSE; 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate } 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate struct bufarea * 252*7c478bd9Sstevel@tonic-gate getblk(bp, blk, size) 253*7c478bd9Sstevel@tonic-gate struct bufarea *bp; 254*7c478bd9Sstevel@tonic-gate daddr32_t blk; 255*7c478bd9Sstevel@tonic-gate int size; 256*7c478bd9Sstevel@tonic-gate { 257*7c478bd9Sstevel@tonic-gate diskaddr_t dblk; 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate dblk = fsbtodb(&sblock, blk); 260*7c478bd9Sstevel@tonic-gate if (bp->b_bno == dblk) 261*7c478bd9Sstevel@tonic-gate return (bp); 262*7c478bd9Sstevel@tonic-gate flush(fswritefd, bp); 263*7c478bd9Sstevel@tonic-gate diskreads++; 264*7c478bd9Sstevel@tonic-gate bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, dblk, (long)size); 265*7c478bd9Sstevel@tonic-gate bp->b_bno = dblk; 266*7c478bd9Sstevel@tonic-gate bp->b_size = size; 267*7c478bd9Sstevel@tonic-gate return (bp); 268*7c478bd9Sstevel@tonic-gate } 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate flush(fd, bp) 271*7c478bd9Sstevel@tonic-gate int fd; 272*7c478bd9Sstevel@tonic-gate struct bufarea *bp; 273*7c478bd9Sstevel@tonic-gate { 274*7c478bd9Sstevel@tonic-gate int i, j; 275*7c478bd9Sstevel@tonic-gate caddr_t sip; 276*7c478bd9Sstevel@tonic-gate long size; 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate if (!bp->b_dirty) 279*7c478bd9Sstevel@tonic-gate return; 280*7c478bd9Sstevel@tonic-gate if (bp->b_errs != 0) 281*7c478bd9Sstevel@tonic-gate pfatal("WRITING ZERO'ED BLOCK %lld TO DISK\n", bp->b_bno); 282*7c478bd9Sstevel@tonic-gate bp->b_dirty = 0; 283*7c478bd9Sstevel@tonic-gate bp->b_errs = 0; 284*7c478bd9Sstevel@tonic-gate bwrite(fd, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size); 285*7c478bd9Sstevel@tonic-gate if (bp != &sblk) 286*7c478bd9Sstevel@tonic-gate return; 287*7c478bd9Sstevel@tonic-gate sip = (caddr_t)sblock.fs_u.fs_csp; 288*7c478bd9Sstevel@tonic-gate for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 289*7c478bd9Sstevel@tonic-gate size = sblock.fs_cssize - i < sblock.fs_bsize ? 290*7c478bd9Sstevel@tonic-gate sblock.fs_cssize - i : sblock.fs_bsize; 291*7c478bd9Sstevel@tonic-gate bwrite(fswritefd, sip, 292*7c478bd9Sstevel@tonic-gate fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), 293*7c478bd9Sstevel@tonic-gate size); 294*7c478bd9Sstevel@tonic-gate sip += size; 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate rwerror(mesg, blk) 299*7c478bd9Sstevel@tonic-gate char *mesg; 300*7c478bd9Sstevel@tonic-gate diskaddr_t blk; 301*7c478bd9Sstevel@tonic-gate { 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate if (preen == 0) 304*7c478bd9Sstevel@tonic-gate printf("\n"); 305*7c478bd9Sstevel@tonic-gate pfatal("CANNOT %s: BLK %lld", mesg, blk); 306*7c478bd9Sstevel@tonic-gate if (reply("CONTINUE") == 0) 307*7c478bd9Sstevel@tonic-gate errexit("Program terminated\n"); 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate ckfini() 311*7c478bd9Sstevel@tonic-gate { 312*7c478bd9Sstevel@tonic-gate struct bufarea *bp, *nbp; 313*7c478bd9Sstevel@tonic-gate int cnt = 0; 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate /* 316*7c478bd9Sstevel@tonic-gate * Mark the filesystem bad if a re-check is required. 317*7c478bd9Sstevel@tonic-gate */ 318*7c478bd9Sstevel@tonic-gate if (dirholes && havesb) { 319*7c478bd9Sstevel@tonic-gate sblock.fs_clean = FSBAD; 320*7c478bd9Sstevel@tonic-gate sblock.fs_state = -(FSOKAY - (long)sblock.fs_time); 321*7c478bd9Sstevel@tonic-gate sbdirty(); 322*7c478bd9Sstevel@tonic-gate } 323*7c478bd9Sstevel@tonic-gate flush(fswritefd, &sblk); 324*7c478bd9Sstevel@tonic-gate if (havesb && sblk.b_bno != SBOFF / dev_bsize) { 325*7c478bd9Sstevel@tonic-gate sblk.b_bno = SBOFF / dev_bsize; 326*7c478bd9Sstevel@tonic-gate sbdirty(); 327*7c478bd9Sstevel@tonic-gate flush(fswritefd, &sblk); 328*7c478bd9Sstevel@tonic-gate } 329*7c478bd9Sstevel@tonic-gate flush(fswritefd, &cgblk); 330*7c478bd9Sstevel@tonic-gate if (cgblk.b_un.b_buf) { 331*7c478bd9Sstevel@tonic-gate free(cgblk.b_un.b_buf); 332*7c478bd9Sstevel@tonic-gate cgblk.b_un.b_buf = NULL; 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) { 335*7c478bd9Sstevel@tonic-gate cnt++; 336*7c478bd9Sstevel@tonic-gate flush(fswritefd, bp); 337*7c478bd9Sstevel@tonic-gate nbp = bp->b_prev; 338*7c478bd9Sstevel@tonic-gate free(bp->b_un.b_buf); 339*7c478bd9Sstevel@tonic-gate free((char *)bp); 340*7c478bd9Sstevel@tonic-gate } 341*7c478bd9Sstevel@tonic-gate pbp = pdirbp = NULL; 342*7c478bd9Sstevel@tonic-gate if (bufhead.b_size != cnt) 343*7c478bd9Sstevel@tonic-gate errexit("Panic: lost %d buffers\n", bufhead.b_size - cnt); 344*7c478bd9Sstevel@tonic-gate if (debug) 345*7c478bd9Sstevel@tonic-gate printf("cache missed %d of %d (%d%%)\n", 346*7c478bd9Sstevel@tonic-gate diskreads, totalreads, 347*7c478bd9Sstevel@tonic-gate totalreads ? diskreads * 100 / totalreads : 0); 348*7c478bd9Sstevel@tonic-gate (void) close(fsreadfd); 349*7c478bd9Sstevel@tonic-gate (void) close(fswritefd); 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate bread(fd, buf, blk, size) 353*7c478bd9Sstevel@tonic-gate int fd; 354*7c478bd9Sstevel@tonic-gate char *buf; 355*7c478bd9Sstevel@tonic-gate diskaddr_t blk; 356*7c478bd9Sstevel@tonic-gate long size; 357*7c478bd9Sstevel@tonic-gate { 358*7c478bd9Sstevel@tonic-gate char *cp; 359*7c478bd9Sstevel@tonic-gate int i; 360*7c478bd9Sstevel@tonic-gate int errs; 361*7c478bd9Sstevel@tonic-gate offset_t offset = ldbtob(blk); 362*7c478bd9Sstevel@tonic-gate offset_t addr; 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate if (debug && (blk < SBLOCK)) { 365*7c478bd9Sstevel@tonic-gate char msg[256]; 366*7c478bd9Sstevel@tonic-gate sprintf(msg, "WARNING: fsck bread() passed blkno < %d (%ld)\n", 367*7c478bd9Sstevel@tonic-gate SBLOCK, blk); 368*7c478bd9Sstevel@tonic-gate printf(msg); 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate if (llseek(fd, offset, 0) < 0) { 371*7c478bd9Sstevel@tonic-gate rwerror("SEEK", blk); 372*7c478bd9Sstevel@tonic-gate } else if (read(fd, buf, (int)size) == size) 373*7c478bd9Sstevel@tonic-gate return (0); 374*7c478bd9Sstevel@tonic-gate rwerror("READ", blk); 375*7c478bd9Sstevel@tonic-gate if (llseek(fd, offset, 0) < 0) { 376*7c478bd9Sstevel@tonic-gate rwerror("SEEK", blk); 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate errs = 0; 379*7c478bd9Sstevel@tonic-gate bzero(buf, (size_t)size); 380*7c478bd9Sstevel@tonic-gate pwarn("THE FOLLOWING SECTORS COULD NOT BE READ:"); 381*7c478bd9Sstevel@tonic-gate for (cp = buf, i = 0; i < btodb(size); i++, cp += DEV_BSIZE) { 382*7c478bd9Sstevel@tonic-gate addr = ldbtob(blk + i); 383*7c478bd9Sstevel@tonic-gate if (llseek(fd, addr, SEEK_CUR) < 0 || 384*7c478bd9Sstevel@tonic-gate read(fd, cp, (int)secsize) < 0) { 385*7c478bd9Sstevel@tonic-gate printf(" %d", blk + i); 386*7c478bd9Sstevel@tonic-gate errs++; 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate } 389*7c478bd9Sstevel@tonic-gate printf("\n"); 390*7c478bd9Sstevel@tonic-gate return (errs); 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate bwrite(fd, buf, blk, size) 394*7c478bd9Sstevel@tonic-gate int fd; 395*7c478bd9Sstevel@tonic-gate char *buf; 396*7c478bd9Sstevel@tonic-gate diskaddr_t blk; 397*7c478bd9Sstevel@tonic-gate long size; 398*7c478bd9Sstevel@tonic-gate { 399*7c478bd9Sstevel@tonic-gate int i; 400*7c478bd9Sstevel@tonic-gate int n; 401*7c478bd9Sstevel@tonic-gate char *cp; 402*7c478bd9Sstevel@tonic-gate offset_t offset = ldbtob(blk); 403*7c478bd9Sstevel@tonic-gate offset_t addr; 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate if (fd < 0) 406*7c478bd9Sstevel@tonic-gate return; 407*7c478bd9Sstevel@tonic-gate if (blk < SBLOCK) { 408*7c478bd9Sstevel@tonic-gate char msg[256]; 409*7c478bd9Sstevel@tonic-gate sprintf(msg, 410*7c478bd9Sstevel@tonic-gate "WARNING: Attempt to write illegal blkno %lld on %s\n", 411*7c478bd9Sstevel@tonic-gate blk, devname); 412*7c478bd9Sstevel@tonic-gate if (debug) 413*7c478bd9Sstevel@tonic-gate printf(msg); 414*7c478bd9Sstevel@tonic-gate return; 415*7c478bd9Sstevel@tonic-gate } 416*7c478bd9Sstevel@tonic-gate if (llseek(fd, offset, 0) < 0) { 417*7c478bd9Sstevel@tonic-gate rwerror("SEEK", blk); 418*7c478bd9Sstevel@tonic-gate } else if (write(fd, buf, (int)size) == size) { 419*7c478bd9Sstevel@tonic-gate fsmodified = 1; 420*7c478bd9Sstevel@tonic-gate return; 421*7c478bd9Sstevel@tonic-gate } 422*7c478bd9Sstevel@tonic-gate rwerror("WRITE", blk); 423*7c478bd9Sstevel@tonic-gate if (llseek(fd, offset, 0) < 0) { 424*7c478bd9Sstevel@tonic-gate rwerror("SEEK", blk); 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate pwarn("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:"); 427*7c478bd9Sstevel@tonic-gate for (cp = buf, i = 0; i < btodb(size); i++, cp += DEV_BSIZE) { 428*7c478bd9Sstevel@tonic-gate n = 0; 429*7c478bd9Sstevel@tonic-gate addr = ldbtob(blk + i); 430*7c478bd9Sstevel@tonic-gate if (llseek(fd, addr, SEEK_CUR) < 0 || 431*7c478bd9Sstevel@tonic-gate (n = write(fd, cp, DEV_BSIZE)) < 0) { 432*7c478bd9Sstevel@tonic-gate printf(" %d", blk + i); 433*7c478bd9Sstevel@tonic-gate } else if (n > 0) { 434*7c478bd9Sstevel@tonic-gate fsmodified = 1; 435*7c478bd9Sstevel@tonic-gate } 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate } 438*7c478bd9Sstevel@tonic-gate printf("\n"); 439*7c478bd9Sstevel@tonic-gate } 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate /* 442*7c478bd9Sstevel@tonic-gate * allocate a data block with the specified number of fragments 443*7c478bd9Sstevel@tonic-gate */ 444*7c478bd9Sstevel@tonic-gate daddr32_t 445*7c478bd9Sstevel@tonic-gate allocblk(frags) 446*7c478bd9Sstevel@tonic-gate int frags; 447*7c478bd9Sstevel@tonic-gate { 448*7c478bd9Sstevel@tonic-gate int i, j, k; 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate if (frags <= 0 || frags > sblock.fs_frag) 451*7c478bd9Sstevel@tonic-gate return (0); 452*7c478bd9Sstevel@tonic-gate for (i = 0; i < maxfsblock - sblock.fs_frag; i += sblock.fs_frag) { 453*7c478bd9Sstevel@tonic-gate for (j = 0; j <= sblock.fs_frag - frags; j++) { 454*7c478bd9Sstevel@tonic-gate if (testbmap(i + j)) 455*7c478bd9Sstevel@tonic-gate continue; 456*7c478bd9Sstevel@tonic-gate for (k = 1; k < frags; k++) 457*7c478bd9Sstevel@tonic-gate if (testbmap(i + j + k)) 458*7c478bd9Sstevel@tonic-gate break; 459*7c478bd9Sstevel@tonic-gate if (k < frags) { 460*7c478bd9Sstevel@tonic-gate j += k; 461*7c478bd9Sstevel@tonic-gate continue; 462*7c478bd9Sstevel@tonic-gate } 463*7c478bd9Sstevel@tonic-gate for (k = 0; k < frags; k++) 464*7c478bd9Sstevel@tonic-gate setbmap(i + j + k); 465*7c478bd9Sstevel@tonic-gate n_blks += frags; 466*7c478bd9Sstevel@tonic-gate return (i + j); 467*7c478bd9Sstevel@tonic-gate } 468*7c478bd9Sstevel@tonic-gate } 469*7c478bd9Sstevel@tonic-gate return (0); 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate /* 473*7c478bd9Sstevel@tonic-gate * Free a previously allocated block 474*7c478bd9Sstevel@tonic-gate */ 475*7c478bd9Sstevel@tonic-gate freeblk(blkno, frags) 476*7c478bd9Sstevel@tonic-gate daddr32_t blkno; 477*7c478bd9Sstevel@tonic-gate int frags; 478*7c478bd9Sstevel@tonic-gate { 479*7c478bd9Sstevel@tonic-gate struct inodesc idesc; 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate idesc.id_blkno = blkno; 482*7c478bd9Sstevel@tonic-gate idesc.id_numfrags = frags; 483*7c478bd9Sstevel@tonic-gate pass4check(&idesc); 484*7c478bd9Sstevel@tonic-gate } 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate /* 487*7c478bd9Sstevel@tonic-gate * Find a pathname 488*7c478bd9Sstevel@tonic-gate */ 489*7c478bd9Sstevel@tonic-gate getpathname(namebuf, curdir, ino) 490*7c478bd9Sstevel@tonic-gate char *namebuf; 491*7c478bd9Sstevel@tonic-gate ino_t curdir, ino; 492*7c478bd9Sstevel@tonic-gate { 493*7c478bd9Sstevel@tonic-gate int len; 494*7c478bd9Sstevel@tonic-gate char *cp; 495*7c478bd9Sstevel@tonic-gate struct inodesc idesc; 496*7c478bd9Sstevel@tonic-gate struct inoinfo *inp; 497*7c478bd9Sstevel@tonic-gate extern int findname(); 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate if (statemap[curdir] != DSTATE && statemap[curdir] != DFOUND) { 500*7c478bd9Sstevel@tonic-gate strcpy(namebuf, "?"); 501*7c478bd9Sstevel@tonic-gate return; 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate bzero((char *)&idesc, sizeof (struct inodesc)); 504*7c478bd9Sstevel@tonic-gate idesc.id_type = DATA; 505*7c478bd9Sstevel@tonic-gate cp = &namebuf[MAXPATHLEN - 1]; 506*7c478bd9Sstevel@tonic-gate *cp = '\0'; 507*7c478bd9Sstevel@tonic-gate if (curdir != ino) { 508*7c478bd9Sstevel@tonic-gate idesc.id_parent = curdir; 509*7c478bd9Sstevel@tonic-gate goto namelookup; 510*7c478bd9Sstevel@tonic-gate } 511*7c478bd9Sstevel@tonic-gate while (ino != UFSROOTINO) { 512*7c478bd9Sstevel@tonic-gate idesc.id_number = ino; 513*7c478bd9Sstevel@tonic-gate idesc.id_func = findino; 514*7c478bd9Sstevel@tonic-gate idesc.id_name = ".."; 515*7c478bd9Sstevel@tonic-gate idesc.id_fix = NOFIX; 516*7c478bd9Sstevel@tonic-gate if ((ckinode(ginode(ino), &idesc) & FOUND) == 0) { 517*7c478bd9Sstevel@tonic-gate inp = getinoinfo(ino); 518*7c478bd9Sstevel@tonic-gate if (inp->i_parent == 0) 519*7c478bd9Sstevel@tonic-gate break; 520*7c478bd9Sstevel@tonic-gate idesc.id_parent = inp->i_parent; 521*7c478bd9Sstevel@tonic-gate } 522*7c478bd9Sstevel@tonic-gate namelookup: 523*7c478bd9Sstevel@tonic-gate idesc.id_number = idesc.id_parent; 524*7c478bd9Sstevel@tonic-gate idesc.id_parent = ino; 525*7c478bd9Sstevel@tonic-gate idesc.id_func = findname; 526*7c478bd9Sstevel@tonic-gate idesc.id_name = namebuf; 527*7c478bd9Sstevel@tonic-gate idesc.id_fix = NOFIX; 528*7c478bd9Sstevel@tonic-gate if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0) 529*7c478bd9Sstevel@tonic-gate break; 530*7c478bd9Sstevel@tonic-gate len = strlen(namebuf); 531*7c478bd9Sstevel@tonic-gate cp -= len; 532*7c478bd9Sstevel@tonic-gate if (cp < &namebuf[MAXNAMLEN]) 533*7c478bd9Sstevel@tonic-gate break; 534*7c478bd9Sstevel@tonic-gate bcopy(namebuf, cp, len); 535*7c478bd9Sstevel@tonic-gate *--cp = '/'; 536*7c478bd9Sstevel@tonic-gate ino = idesc.id_number; 537*7c478bd9Sstevel@tonic-gate } 538*7c478bd9Sstevel@tonic-gate if (ino != UFSROOTINO) { 539*7c478bd9Sstevel@tonic-gate strcpy(namebuf, "?"); 540*7c478bd9Sstevel@tonic-gate return; 541*7c478bd9Sstevel@tonic-gate } 542*7c478bd9Sstevel@tonic-gate bcopy(cp, namebuf, &namebuf[MAXPATHLEN] - cp); 543*7c478bd9Sstevel@tonic-gate } 544*7c478bd9Sstevel@tonic-gate 545*7c478bd9Sstevel@tonic-gate void 546*7c478bd9Sstevel@tonic-gate catch() 547*7c478bd9Sstevel@tonic-gate { 548*7c478bd9Sstevel@tonic-gate ckfini(); 549*7c478bd9Sstevel@tonic-gate exit(37); 550*7c478bd9Sstevel@tonic-gate } 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate /* 553*7c478bd9Sstevel@tonic-gate * When preening, allow a single quit to signal 554*7c478bd9Sstevel@tonic-gate * a special exit after filesystem checks complete 555*7c478bd9Sstevel@tonic-gate * so that reboot sequence may be interrupted. 556*7c478bd9Sstevel@tonic-gate */ 557*7c478bd9Sstevel@tonic-gate void 558*7c478bd9Sstevel@tonic-gate catchquit() 559*7c478bd9Sstevel@tonic-gate { 560*7c478bd9Sstevel@tonic-gate extern returntosingle; 561*7c478bd9Sstevel@tonic-gate 562*7c478bd9Sstevel@tonic-gate printf("returning to single-user after filesystem check\n"); 563*7c478bd9Sstevel@tonic-gate returntosingle = 1; 564*7c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_DFL); 565*7c478bd9Sstevel@tonic-gate } 566*7c478bd9Sstevel@tonic-gate 567*7c478bd9Sstevel@tonic-gate /* 568*7c478bd9Sstevel@tonic-gate * Ignore a single quit signal; wait and flush just in case. 569*7c478bd9Sstevel@tonic-gate * Used by child processes in preen. 570*7c478bd9Sstevel@tonic-gate */ 571*7c478bd9Sstevel@tonic-gate void 572*7c478bd9Sstevel@tonic-gate voidquit() 573*7c478bd9Sstevel@tonic-gate { 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate sleep(1); 576*7c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_IGN); 577*7c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_DFL); 578*7c478bd9Sstevel@tonic-gate } 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate /* 581*7c478bd9Sstevel@tonic-gate * determine whether an inode should be fixed. 582*7c478bd9Sstevel@tonic-gate */ 583*7c478bd9Sstevel@tonic-gate dofix(idesc, msg) 584*7c478bd9Sstevel@tonic-gate struct inodesc *idesc; 585*7c478bd9Sstevel@tonic-gate char *msg; 586*7c478bd9Sstevel@tonic-gate { 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate switch (idesc->id_fix) { 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate case DONTKNOW: 591*7c478bd9Sstevel@tonic-gate if (idesc->id_type == DATA) 592*7c478bd9Sstevel@tonic-gate direrror(idesc->id_number, msg); 593*7c478bd9Sstevel@tonic-gate else 594*7c478bd9Sstevel@tonic-gate pwarn(msg); 595*7c478bd9Sstevel@tonic-gate if (preen) { 596*7c478bd9Sstevel@tonic-gate printf(" (SALVAGED)\n"); 597*7c478bd9Sstevel@tonic-gate idesc->id_fix = FIX; 598*7c478bd9Sstevel@tonic-gate return (ALTERED); 599*7c478bd9Sstevel@tonic-gate } 600*7c478bd9Sstevel@tonic-gate if (reply("SALVAGE") == 0) { 601*7c478bd9Sstevel@tonic-gate idesc->id_fix = NOFIX; 602*7c478bd9Sstevel@tonic-gate return (0); 603*7c478bd9Sstevel@tonic-gate } 604*7c478bd9Sstevel@tonic-gate idesc->id_fix = FIX; 605*7c478bd9Sstevel@tonic-gate return (ALTERED); 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate case FIX: 608*7c478bd9Sstevel@tonic-gate return (ALTERED); 609*7c478bd9Sstevel@tonic-gate 610*7c478bd9Sstevel@tonic-gate case NOFIX: 611*7c478bd9Sstevel@tonic-gate return (0); 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate default: 614*7c478bd9Sstevel@tonic-gate errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix); 615*7c478bd9Sstevel@tonic-gate } 616*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 617*7c478bd9Sstevel@tonic-gate } 618*7c478bd9Sstevel@tonic-gate 619*7c478bd9Sstevel@tonic-gate /* VARARGS1 */ 620*7c478bd9Sstevel@tonic-gate errexit(s1, s2, s3, s4) 621*7c478bd9Sstevel@tonic-gate char *s1; 622*7c478bd9Sstevel@tonic-gate { 623*7c478bd9Sstevel@tonic-gate extern void write_altsb(int); 624*7c478bd9Sstevel@tonic-gate 625*7c478bd9Sstevel@tonic-gate if (errorlocked) { 626*7c478bd9Sstevel@tonic-gate if (havesb) { 627*7c478bd9Sstevel@tonic-gate sblock.fs_clean = FSBAD; 628*7c478bd9Sstevel@tonic-gate sblock.fs_state = -(FSOKAY - (long)sblock.fs_time); 629*7c478bd9Sstevel@tonic-gate sbdirty(); 630*7c478bd9Sstevel@tonic-gate write_altsb(fswritefd); 631*7c478bd9Sstevel@tonic-gate flush(fswritefd, &sblk); 632*7c478bd9Sstevel@tonic-gate } 633*7c478bd9Sstevel@tonic-gate } 634*7c478bd9Sstevel@tonic-gate printf(s1, s2, s3, s4); 635*7c478bd9Sstevel@tonic-gate exit(39); 636*7c478bd9Sstevel@tonic-gate } 637*7c478bd9Sstevel@tonic-gate 638*7c478bd9Sstevel@tonic-gate /* 639*7c478bd9Sstevel@tonic-gate * An unexpected inconsistency occured. 640*7c478bd9Sstevel@tonic-gate * Die if preening, otherwise just print message and continue. 641*7c478bd9Sstevel@tonic-gate */ 642*7c478bd9Sstevel@tonic-gate /* VARARGS1 */ 643*7c478bd9Sstevel@tonic-gate pfatal(s, a1, a2, a3) 644*7c478bd9Sstevel@tonic-gate char *s; 645*7c478bd9Sstevel@tonic-gate { 646*7c478bd9Sstevel@tonic-gate if (preen) { 647*7c478bd9Sstevel@tonic-gate printf("%s: ", devname); 648*7c478bd9Sstevel@tonic-gate printf(s, a1, a2, a3); 649*7c478bd9Sstevel@tonic-gate printf("\n"); 650*7c478bd9Sstevel@tonic-gate printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", 651*7c478bd9Sstevel@tonic-gate devname); 652*7c478bd9Sstevel@tonic-gate if (havesb) { 653*7c478bd9Sstevel@tonic-gate sblock.fs_clean = FSBAD; 654*7c478bd9Sstevel@tonic-gate sblock.fs_state = -(FSOKAY - (long)sblock.fs_time); 655*7c478bd9Sstevel@tonic-gate sbdirty(); 656*7c478bd9Sstevel@tonic-gate flush(fswritefd, &sblk); 657*7c478bd9Sstevel@tonic-gate } 658*7c478bd9Sstevel@tonic-gate exit(36); 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate printf(s, a1, a2, a3); 661*7c478bd9Sstevel@tonic-gate } 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate /* 664*7c478bd9Sstevel@tonic-gate * Pwarn just prints a message when not preening, 665*7c478bd9Sstevel@tonic-gate * or a warning (preceded by filename) when preening. 666*7c478bd9Sstevel@tonic-gate */ 667*7c478bd9Sstevel@tonic-gate /* VARARGS1 */ 668*7c478bd9Sstevel@tonic-gate pwarn(s, a1, a2, a3, a4, a5, a6) 669*7c478bd9Sstevel@tonic-gate char *s; 670*7c478bd9Sstevel@tonic-gate { 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate if (preen) 673*7c478bd9Sstevel@tonic-gate printf("%s: ", devname); 674*7c478bd9Sstevel@tonic-gate printf(s, a1, a2, a3, a4, a5, a6); 675*7c478bd9Sstevel@tonic-gate } 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate #ifndef lint 678*7c478bd9Sstevel@tonic-gate /* 679*7c478bd9Sstevel@tonic-gate * Stub for routines from kernel. 680*7c478bd9Sstevel@tonic-gate */ 681*7c478bd9Sstevel@tonic-gate panic(s) 682*7c478bd9Sstevel@tonic-gate char *s; 683*7c478bd9Sstevel@tonic-gate { 684*7c478bd9Sstevel@tonic-gate 685*7c478bd9Sstevel@tonic-gate pfatal("INTERNAL INCONSISTENCY:"); 686*7c478bd9Sstevel@tonic-gate errexit(s); 687*7c478bd9Sstevel@tonic-gate } 688*7c478bd9Sstevel@tonic-gate #define CE_PANIC 3 689*7c478bd9Sstevel@tonic-gate void 690*7c478bd9Sstevel@tonic-gate cmn_err(level, s) 691*7c478bd9Sstevel@tonic-gate int level; 692*7c478bd9Sstevel@tonic-gate char *s; 693*7c478bd9Sstevel@tonic-gate { 694*7c478bd9Sstevel@tonic-gate 695*7c478bd9Sstevel@tonic-gate if (level == CE_PANIC) { 696*7c478bd9Sstevel@tonic-gate pfatal("INTERNAL INCONSISTENCY:"); 697*7c478bd9Sstevel@tonic-gate errexit(s); 698*7c478bd9Sstevel@tonic-gate } 699*7c478bd9Sstevel@tonic-gate else 700*7c478bd9Sstevel@tonic-gate printf(s); 701*7c478bd9Sstevel@tonic-gate } 702*7c478bd9Sstevel@tonic-gate #endif 703*7c478bd9Sstevel@tonic-gate 704*7c478bd9Sstevel@tonic-gate /* 705*7c478bd9Sstevel@tonic-gate * Check to see if unraw version of name is already mounted. 706*7c478bd9Sstevel@tonic-gate * Since we do not believe /etc/mnttab, we stat the mount point 707*7c478bd9Sstevel@tonic-gate * to see if it is really looks mounted. 708*7c478bd9Sstevel@tonic-gate */ 709*7c478bd9Sstevel@tonic-gate mounted(name) 710*7c478bd9Sstevel@tonic-gate char *name; 711*7c478bd9Sstevel@tonic-gate { 712*7c478bd9Sstevel@tonic-gate int found = 0; 713*7c478bd9Sstevel@tonic-gate struct mnttab mnt; 714*7c478bd9Sstevel@tonic-gate FILE *mnttab; 715*7c478bd9Sstevel@tonic-gate struct stat64 device_stat, mount_stat; 716*7c478bd9Sstevel@tonic-gate char *blkname, *unrawname(); 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate mnttab = fopen(MNTTAB, "r"); 719*7c478bd9Sstevel@tonic-gate if (mnttab == NULL) { 720*7c478bd9Sstevel@tonic-gate return (0); 721*7c478bd9Sstevel@tonic-gate } 722*7c478bd9Sstevel@tonic-gate blkname = unrawname(name); 723*7c478bd9Sstevel@tonic-gate while ((getmntent(mnttab, &mnt)) == NULL) { 724*7c478bd9Sstevel@tonic-gate if (strcmp(mnt.mnt_fstype, MNTTYPE_UFS) != 0) { 725*7c478bd9Sstevel@tonic-gate continue; 726*7c478bd9Sstevel@tonic-gate } 727*7c478bd9Sstevel@tonic-gate if (strcmp(blkname, mnt.mnt_special) == 0) { 728*7c478bd9Sstevel@tonic-gate stat64(mnt.mnt_mountp, &mount_stat); 729*7c478bd9Sstevel@tonic-gate stat64(mnt.mnt_special, &device_stat); 730*7c478bd9Sstevel@tonic-gate if (device_stat.st_rdev == mount_stat.st_dev) { 731*7c478bd9Sstevel@tonic-gate if (hasmntopt(&mnt, MNTOPT_RO) != 0) 732*7c478bd9Sstevel@tonic-gate found = 2; /* mounted as RO */ 733*7c478bd9Sstevel@tonic-gate else 734*7c478bd9Sstevel@tonic-gate found = 1; /* mounted as R/W */ 735*7c478bd9Sstevel@tonic-gate } 736*7c478bd9Sstevel@tonic-gate if (mount_point == NULL) { 737*7c478bd9Sstevel@tonic-gate mount_point = strdup(mnt.mnt_mountp); 738*7c478bd9Sstevel@tonic-gate if (mount_point == NULL) { 739*7c478bd9Sstevel@tonic-gate printf("fsck: memory allocation" 740*7c478bd9Sstevel@tonic-gate " failure\n"); 741*7c478bd9Sstevel@tonic-gate exit(39); 742*7c478bd9Sstevel@tonic-gate } 743*7c478bd9Sstevel@tonic-gate } 744*7c478bd9Sstevel@tonic-gate break; 745*7c478bd9Sstevel@tonic-gate } 746*7c478bd9Sstevel@tonic-gate } 747*7c478bd9Sstevel@tonic-gate fclose(mnttab); 748*7c478bd9Sstevel@tonic-gate return (found); 749*7c478bd9Sstevel@tonic-gate } 750*7c478bd9Sstevel@tonic-gate 751*7c478bd9Sstevel@tonic-gate /* 752*7c478bd9Sstevel@tonic-gate * Check to see if name corresponds to an entry in vfstab, and that the entry 753*7c478bd9Sstevel@tonic-gate * does not have option ro. 754*7c478bd9Sstevel@tonic-gate */ 755*7c478bd9Sstevel@tonic-gate writable(name) 756*7c478bd9Sstevel@tonic-gate char *name; 757*7c478bd9Sstevel@tonic-gate { 758*7c478bd9Sstevel@tonic-gate int rw = 1; 759*7c478bd9Sstevel@tonic-gate struct vfstab vfsbuf; 760*7c478bd9Sstevel@tonic-gate FILE *vfstab; 761*7c478bd9Sstevel@tonic-gate char *blkname, *unrawname(); 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate vfstab = fopen(VFSTAB, "r"); 764*7c478bd9Sstevel@tonic-gate if (vfstab == NULL) { 765*7c478bd9Sstevel@tonic-gate printf("can't open %s\n", VFSTAB); 766*7c478bd9Sstevel@tonic-gate return (1); 767*7c478bd9Sstevel@tonic-gate } 768*7c478bd9Sstevel@tonic-gate blkname = unrawname(name); 769*7c478bd9Sstevel@tonic-gate if ((getvfsspec(vfstab, &vfsbuf, blkname) == 0) && 770*7c478bd9Sstevel@tonic-gate (vfsbuf.vfs_fstype != NULL) && 771*7c478bd9Sstevel@tonic-gate (strcmp(vfsbuf.vfs_fstype, MNTTYPE_UFS) == 0) && 772*7c478bd9Sstevel@tonic-gate (hasvfsopt(&vfsbuf, MNTOPT_RO))) { 773*7c478bd9Sstevel@tonic-gate rw = 0; 774*7c478bd9Sstevel@tonic-gate } 775*7c478bd9Sstevel@tonic-gate fclose(vfstab); 776*7c478bd9Sstevel@tonic-gate return (rw); 777*7c478bd9Sstevel@tonic-gate } 778*7c478bd9Sstevel@tonic-gate 779*7c478bd9Sstevel@tonic-gate /* 780*7c478bd9Sstevel@tonic-gate * debugclean 781*7c478bd9Sstevel@tonic-gate */ 782*7c478bd9Sstevel@tonic-gate debugclean() 783*7c478bd9Sstevel@tonic-gate { 784*7c478bd9Sstevel@tonic-gate char s[256]; 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate if (debug == 0) 787*7c478bd9Sstevel@tonic-gate return; 788*7c478bd9Sstevel@tonic-gate 789*7c478bd9Sstevel@tonic-gate if ((iscorrupt == 0) && (isdirty == 0)) 790*7c478bd9Sstevel@tonic-gate return; 791*7c478bd9Sstevel@tonic-gate 792*7c478bd9Sstevel@tonic-gate if ((sblock.fs_clean != FSSTABLE) && (sblock.fs_clean != FSCLEAN) && 793*7c478bd9Sstevel@tonic-gate (sblock.fs_clean != FSLOG || !islog || !islogok)) 794*7c478bd9Sstevel@tonic-gate return; 795*7c478bd9Sstevel@tonic-gate 796*7c478bd9Sstevel@tonic-gate if (FSOKAY != (sblock.fs_state + sblock.fs_time) && !errorlocked) 797*7c478bd9Sstevel@tonic-gate return; 798*7c478bd9Sstevel@tonic-gate 799*7c478bd9Sstevel@tonic-gate sprintf(s, 800*7c478bd9Sstevel@tonic-gate "WARNING: inconsistencies detected on `%s' filesystem %s", 801*7c478bd9Sstevel@tonic-gate sblock.fs_clean == FSSTABLE ? "stable" : 802*7c478bd9Sstevel@tonic-gate sblock.fs_clean == FSLOG ? "logging" : 803*7c478bd9Sstevel@tonic-gate sblock.fs_clean == FSFIX ? "being fixed" : "clean", devname); 804*7c478bd9Sstevel@tonic-gate printf("%s\n", s); 805*7c478bd9Sstevel@tonic-gate } 806*7c478bd9Sstevel@tonic-gate 807*7c478bd9Sstevel@tonic-gate /* 808*7c478bd9Sstevel@tonic-gate * updateclean 809*7c478bd9Sstevel@tonic-gate * Carefully and transparently update the clean flag. 810*7c478bd9Sstevel@tonic-gate */ 811*7c478bd9Sstevel@tonic-gate updateclean() 812*7c478bd9Sstevel@tonic-gate { 813*7c478bd9Sstevel@tonic-gate struct bufarea cleanbuf; 814*7c478bd9Sstevel@tonic-gate int size; 815*7c478bd9Sstevel@tonic-gate daddr32_t bno; 816*7c478bd9Sstevel@tonic-gate int fsclean; 817*7c478bd9Sstevel@tonic-gate int fsreclaim; 818*7c478bd9Sstevel@tonic-gate int fsflags; 819*7c478bd9Sstevel@tonic-gate int r; 820*7c478bd9Sstevel@tonic-gate daddr32_t fslogbno; 821*7c478bd9Sstevel@tonic-gate offset_t sblkoff; 822*7c478bd9Sstevel@tonic-gate time_t t; 823*7c478bd9Sstevel@tonic-gate 824*7c478bd9Sstevel@tonic-gate /* 825*7c478bd9Sstevel@tonic-gate * debug stuff 826*7c478bd9Sstevel@tonic-gate */ 827*7c478bd9Sstevel@tonic-gate debugclean(); 828*7c478bd9Sstevel@tonic-gate 829*7c478bd9Sstevel@tonic-gate /* 830*7c478bd9Sstevel@tonic-gate * set fsclean to its appropriate value 831*7c478bd9Sstevel@tonic-gate */ 832*7c478bd9Sstevel@tonic-gate fslogbno = sblock.fs_logbno; 833*7c478bd9Sstevel@tonic-gate fsclean = sblock.fs_clean; 834*7c478bd9Sstevel@tonic-gate fsreclaim = sblock.fs_reclaim; 835*7c478bd9Sstevel@tonic-gate fsflags = sblock.fs_flags; 836*7c478bd9Sstevel@tonic-gate if (FSOKAY != (sblock.fs_state + sblock.fs_time) && !errorlocked) 837*7c478bd9Sstevel@tonic-gate fsclean = FSACTIVE; 838*7c478bd9Sstevel@tonic-gate 839*7c478bd9Sstevel@tonic-gate /* if ufs log is not okay, clear it */ 840*7c478bd9Sstevel@tonic-gate if (fslogbno && !(islog && islogok)) { 841*7c478bd9Sstevel@tonic-gate fsclean = FSACTIVE; 842*7c478bd9Sstevel@tonic-gate fslogbno = 0; 843*7c478bd9Sstevel@tonic-gate } 844*7c478bd9Sstevel@tonic-gate 845*7c478bd9Sstevel@tonic-gate /* 846*7c478bd9Sstevel@tonic-gate * if necessary, update fs_clean and fs_state 847*7c478bd9Sstevel@tonic-gate */ 848*7c478bd9Sstevel@tonic-gate switch (fsclean) { 849*7c478bd9Sstevel@tonic-gate 850*7c478bd9Sstevel@tonic-gate case FSACTIVE: 851*7c478bd9Sstevel@tonic-gate if (!iscorrupt) { 852*7c478bd9Sstevel@tonic-gate fsclean = FSSTABLE; 853*7c478bd9Sstevel@tonic-gate fsreclaim = 0; 854*7c478bd9Sstevel@tonic-gate } 855*7c478bd9Sstevel@tonic-gate break; 856*7c478bd9Sstevel@tonic-gate 857*7c478bd9Sstevel@tonic-gate case FSCLEAN: 858*7c478bd9Sstevel@tonic-gate case FSSTABLE: 859*7c478bd9Sstevel@tonic-gate if (iscorrupt) 860*7c478bd9Sstevel@tonic-gate fsclean = FSACTIVE; 861*7c478bd9Sstevel@tonic-gate else 862*7c478bd9Sstevel@tonic-gate fsreclaim = 0; 863*7c478bd9Sstevel@tonic-gate break; 864*7c478bd9Sstevel@tonic-gate 865*7c478bd9Sstevel@tonic-gate case FSLOG: 866*7c478bd9Sstevel@tonic-gate if (iscorrupt) 867*7c478bd9Sstevel@tonic-gate fsclean = FSACTIVE; 868*7c478bd9Sstevel@tonic-gate else if (!islog) { 869*7c478bd9Sstevel@tonic-gate fsreclaim = 0; 870*7c478bd9Sstevel@tonic-gate fsclean = FSSTABLE; 871*7c478bd9Sstevel@tonic-gate } else if (fflag) 872*7c478bd9Sstevel@tonic-gate fsreclaim = 0; 873*7c478bd9Sstevel@tonic-gate break; 874*7c478bd9Sstevel@tonic-gate 875*7c478bd9Sstevel@tonic-gate case FSFIX: 876*7c478bd9Sstevel@tonic-gate fsreclaim = needs_reclaim; 877*7c478bd9Sstevel@tonic-gate fsclean = FSBAD; 878*7c478bd9Sstevel@tonic-gate if (errorlocked && !iscorrupt) { 879*7c478bd9Sstevel@tonic-gate fsclean = islog? FSLOG: FSCLEAN; 880*7c478bd9Sstevel@tonic-gate } 881*7c478bd9Sstevel@tonic-gate break; 882*7c478bd9Sstevel@tonic-gate 883*7c478bd9Sstevel@tonic-gate default: 884*7c478bd9Sstevel@tonic-gate if (iscorrupt) 885*7c478bd9Sstevel@tonic-gate fsclean = FSACTIVE; 886*7c478bd9Sstevel@tonic-gate else { 887*7c478bd9Sstevel@tonic-gate fsclean = FSSTABLE; 888*7c478bd9Sstevel@tonic-gate fsreclaim = 0; 889*7c478bd9Sstevel@tonic-gate } 890*7c478bd9Sstevel@tonic-gate } 891*7c478bd9Sstevel@tonic-gate 892*7c478bd9Sstevel@tonic-gate if (largefile_count > 0) 893*7c478bd9Sstevel@tonic-gate fsflags |= FSLARGEFILES; 894*7c478bd9Sstevel@tonic-gate else 895*7c478bd9Sstevel@tonic-gate fsflags &= ~FSLARGEFILES; 896*7c478bd9Sstevel@tonic-gate 897*7c478bd9Sstevel@tonic-gate /* 898*7c478bd9Sstevel@tonic-gate * fs is unchanged, do nothing 899*7c478bd9Sstevel@tonic-gate */ 900*7c478bd9Sstevel@tonic-gate if (debug) 901*7c478bd9Sstevel@tonic-gate printf("** largefile count=%d, fs.fs_flags=%x\n", 902*7c478bd9Sstevel@tonic-gate largefile_count, sblock.fs_flags); 903*7c478bd9Sstevel@tonic-gate 904*7c478bd9Sstevel@tonic-gate if ((!isdirty) && (fsflags == sblock.fs_flags) && 905*7c478bd9Sstevel@tonic-gate (fslogbno == sblock.fs_logbno) && 906*7c478bd9Sstevel@tonic-gate (sblock.fs_clean == fsclean) && (sblock.fs_reclaim == fsreclaim) && 907*7c478bd9Sstevel@tonic-gate (FSOKAY == (sblock.fs_state + sblock.fs_time))) { 908*7c478bd9Sstevel@tonic-gate if (islog && !islogok) 909*7c478bd9Sstevel@tonic-gate (void) ioctl(fswritefd, _FIOLOGRESET, NULL); 910*7c478bd9Sstevel@tonic-gate 911*7c478bd9Sstevel@tonic-gate if (errorlocked) { 912*7c478bd9Sstevel@tonic-gate if (!do_errorlock(LOCKFS_ULOCK)) 913*7c478bd9Sstevel@tonic-gate pwarn( 914*7c478bd9Sstevel@tonic-gate "updateclean(unchanged): unlock(LOCKFS_ULOCK) failed\n"); 915*7c478bd9Sstevel@tonic-gate } 916*7c478bd9Sstevel@tonic-gate return; 917*7c478bd9Sstevel@tonic-gate } 918*7c478bd9Sstevel@tonic-gate 919*7c478bd9Sstevel@tonic-gate /* 920*7c478bd9Sstevel@tonic-gate * if user allows, update superblock state 921*7c478bd9Sstevel@tonic-gate */ 922*7c478bd9Sstevel@tonic-gate if (!isdirty && !preen && 923*7c478bd9Sstevel@tonic-gate (reply("FILE SYSTEM STATE IN SUPERBLOCK IS WRONG; FIX") == 0)) 924*7c478bd9Sstevel@tonic-gate return; 925*7c478bd9Sstevel@tonic-gate 926*7c478bd9Sstevel@tonic-gate (void) time(&t); 927*7c478bd9Sstevel@tonic-gate sblock.fs_time = (time32_t)t; 928*7c478bd9Sstevel@tonic-gate if (debug) 929*7c478bd9Sstevel@tonic-gate printclean(); 930*7c478bd9Sstevel@tonic-gate sblock.fs_logbno = fslogbno; 931*7c478bd9Sstevel@tonic-gate sblock.fs_clean = fsclean; 932*7c478bd9Sstevel@tonic-gate sblock.fs_state = FSOKAY - (long)sblock.fs_time; 933*7c478bd9Sstevel@tonic-gate sblock.fs_reclaim = fsreclaim; 934*7c478bd9Sstevel@tonic-gate sblock.fs_flags = fsflags; 935*7c478bd9Sstevel@tonic-gate 936*7c478bd9Sstevel@tonic-gate /* 937*7c478bd9Sstevel@tonic-gate * if superblock can't be written, return 938*7c478bd9Sstevel@tonic-gate */ 939*7c478bd9Sstevel@tonic-gate if (fswritefd < 0) 940*7c478bd9Sstevel@tonic-gate return; 941*7c478bd9Sstevel@tonic-gate 942*7c478bd9Sstevel@tonic-gate /* 943*7c478bd9Sstevel@tonic-gate * read private copy of superblock, update clean flag, and write it 944*7c478bd9Sstevel@tonic-gate */ 945*7c478bd9Sstevel@tonic-gate bno = sblk.b_bno; 946*7c478bd9Sstevel@tonic-gate size = sblk.b_size; 947*7c478bd9Sstevel@tonic-gate 948*7c478bd9Sstevel@tonic-gate sblkoff = ldbtob(bno); 949*7c478bd9Sstevel@tonic-gate 950*7c478bd9Sstevel@tonic-gate if ((cleanbuf.b_un.b_buf = malloc(size)) == NULL) 951*7c478bd9Sstevel@tonic-gate errexit("out of memory"); 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate if (llseek(fsreadfd, sblkoff, 0) == -1) 954*7c478bd9Sstevel@tonic-gate return; 955*7c478bd9Sstevel@tonic-gate if (read(fsreadfd, cleanbuf.b_un.b_buf, (int)size) != size) 956*7c478bd9Sstevel@tonic-gate return; 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate cleanbuf.b_un.b_fs->fs_logbno = sblock.fs_logbno; 959*7c478bd9Sstevel@tonic-gate cleanbuf.b_un.b_fs->fs_clean = sblock.fs_clean; 960*7c478bd9Sstevel@tonic-gate cleanbuf.b_un.b_fs->fs_state = sblock.fs_state; 961*7c478bd9Sstevel@tonic-gate cleanbuf.b_un.b_fs->fs_time = sblock.fs_time; 962*7c478bd9Sstevel@tonic-gate cleanbuf.b_un.b_fs->fs_reclaim = sblock.fs_reclaim; 963*7c478bd9Sstevel@tonic-gate cleanbuf.b_un.b_fs->fs_flags = sblock.fs_flags; 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate if (llseek(fswritefd, sblkoff, 0) == -1) 966*7c478bd9Sstevel@tonic-gate return; 967*7c478bd9Sstevel@tonic-gate if (write(fswritefd, cleanbuf.b_un.b_buf, (int)size) != size) 968*7c478bd9Sstevel@tonic-gate return; 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate /* 971*7c478bd9Sstevel@tonic-gate * 1208040 972*7c478bd9Sstevel@tonic-gate * If we had to use -b to grab an alternate superblock, then we 973*7c478bd9Sstevel@tonic-gate * likely had to do so because of unacceptable differences between 974*7c478bd9Sstevel@tonic-gate * the main and alternate superblocks. SO, we had better update 975*7c478bd9Sstevel@tonic-gate * the alternate superblock as well, or we'll just fail again 976*7c478bd9Sstevel@tonic-gate * the next time we attempt to run fsck! 977*7c478bd9Sstevel@tonic-gate */ 978*7c478bd9Sstevel@tonic-gate if (bflag) { 979*7c478bd9Sstevel@tonic-gate extern struct bufarea asblk; 980*7c478bd9Sstevel@tonic-gate 981*7c478bd9Sstevel@tonic-gate if (llseek(fswritefd, ldbtob(asblk.b_bno), 0) == -1) 982*7c478bd9Sstevel@tonic-gate return; 983*7c478bd9Sstevel@tonic-gate if (write(fswritefd, cleanbuf.b_un.b_buf, (int)size) != size) 984*7c478bd9Sstevel@tonic-gate return; 985*7c478bd9Sstevel@tonic-gate } 986*7c478bd9Sstevel@tonic-gate 987*7c478bd9Sstevel@tonic-gate if (islog && !islogok) 988*7c478bd9Sstevel@tonic-gate (void) ioctl(fswritefd, _FIOLOGRESET, NULL); 989*7c478bd9Sstevel@tonic-gate 990*7c478bd9Sstevel@tonic-gate if (errorlocked) { 991*7c478bd9Sstevel@tonic-gate if (!do_errorlock(LOCKFS_ULOCK)) 992*7c478bd9Sstevel@tonic-gate pwarn( 993*7c478bd9Sstevel@tonic-gate "updateclean(changed): unlock(LOCKFS_ULOCK) failed\n"); 994*7c478bd9Sstevel@tonic-gate } 995*7c478bd9Sstevel@tonic-gate } 996*7c478bd9Sstevel@tonic-gate 997*7c478bd9Sstevel@tonic-gate /* 998*7c478bd9Sstevel@tonic-gate * print out clean info 999*7c478bd9Sstevel@tonic-gate */ 1000*7c478bd9Sstevel@tonic-gate printclean() 1001*7c478bd9Sstevel@tonic-gate { 1002*7c478bd9Sstevel@tonic-gate char *s; 1003*7c478bd9Sstevel@tonic-gate 1004*7c478bd9Sstevel@tonic-gate if (FSOKAY != (sblock.fs_state + sblock.fs_time) && !errorlocked) 1005*7c478bd9Sstevel@tonic-gate s = "unknown"; 1006*7c478bd9Sstevel@tonic-gate else 1007*7c478bd9Sstevel@tonic-gate switch (sblock.fs_clean) { 1008*7c478bd9Sstevel@tonic-gate 1009*7c478bd9Sstevel@tonic-gate case FSACTIVE: 1010*7c478bd9Sstevel@tonic-gate s = "active"; 1011*7c478bd9Sstevel@tonic-gate break; 1012*7c478bd9Sstevel@tonic-gate 1013*7c478bd9Sstevel@tonic-gate case FSCLEAN: 1014*7c478bd9Sstevel@tonic-gate s = "clean"; 1015*7c478bd9Sstevel@tonic-gate break; 1016*7c478bd9Sstevel@tonic-gate 1017*7c478bd9Sstevel@tonic-gate case FSSTABLE: 1018*7c478bd9Sstevel@tonic-gate s = "stable"; 1019*7c478bd9Sstevel@tonic-gate break; 1020*7c478bd9Sstevel@tonic-gate 1021*7c478bd9Sstevel@tonic-gate case FSLOG: 1022*7c478bd9Sstevel@tonic-gate s = "logging"; 1023*7c478bd9Sstevel@tonic-gate break; 1024*7c478bd9Sstevel@tonic-gate 1025*7c478bd9Sstevel@tonic-gate case FSBAD: 1026*7c478bd9Sstevel@tonic-gate s = "is bad"; 1027*7c478bd9Sstevel@tonic-gate break; 1028*7c478bd9Sstevel@tonic-gate 1029*7c478bd9Sstevel@tonic-gate case FSFIX: 1030*7c478bd9Sstevel@tonic-gate s = "being fixed"; 1031*7c478bd9Sstevel@tonic-gate break; 1032*7c478bd9Sstevel@tonic-gate 1033*7c478bd9Sstevel@tonic-gate default: 1034*7c478bd9Sstevel@tonic-gate s = "unknown"; 1035*7c478bd9Sstevel@tonic-gate } 1036*7c478bd9Sstevel@tonic-gate 1037*7c478bd9Sstevel@tonic-gate if (preen) 1038*7c478bd9Sstevel@tonic-gate pwarn("is %s.\n", s); 1039*7c478bd9Sstevel@tonic-gate else 1040*7c478bd9Sstevel@tonic-gate printf("** %s is %s.\n", devname, s); 1041*7c478bd9Sstevel@tonic-gate } 1042*7c478bd9Sstevel@tonic-gate 1043*7c478bd9Sstevel@tonic-gate /* see if all numbers */ 1044*7c478bd9Sstevel@tonic-gate numbers(yp) 1045*7c478bd9Sstevel@tonic-gate char *yp; 1046*7c478bd9Sstevel@tonic-gate { 1047*7c478bd9Sstevel@tonic-gate if (yp == NULL) 1048*7c478bd9Sstevel@tonic-gate return (0); 1049*7c478bd9Sstevel@tonic-gate while ('0' <= *yp && *yp <= '9') 1050*7c478bd9Sstevel@tonic-gate yp++; 1051*7c478bd9Sstevel@tonic-gate if (*yp) 1052*7c478bd9Sstevel@tonic-gate return (0); 1053*7c478bd9Sstevel@tonic-gate return (1); 1054*7c478bd9Sstevel@tonic-gate } 1055*7c478bd9Sstevel@tonic-gate 1056*7c478bd9Sstevel@tonic-gate is_errorlocked(char *fs) 1057*7c478bd9Sstevel@tonic-gate { 1058*7c478bd9Sstevel@tonic-gate struct stat64 statb; 1059*7c478bd9Sstevel@tonic-gate char *mountp; 1060*7c478bd9Sstevel@tonic-gate static char *getmountp(char *); 1061*7c478bd9Sstevel@tonic-gate char *unrawname(char *); 1062*7c478bd9Sstevel@tonic-gate 1063*7c478bd9Sstevel@tonic-gate mountp = NULL; 1064*7c478bd9Sstevel@tonic-gate 1065*7c478bd9Sstevel@tonic-gate if (!fs) 1066*7c478bd9Sstevel@tonic-gate return (0); 1067*7c478bd9Sstevel@tonic-gate 1068*7c478bd9Sstevel@tonic-gate if (stat64(fs, &statb) < 0) 1069*7c478bd9Sstevel@tonic-gate return (0); 1070*7c478bd9Sstevel@tonic-gate 1071*7c478bd9Sstevel@tonic-gate if (S_ISDIR(statb.st_mode)) { 1072*7c478bd9Sstevel@tonic-gate mountp = fs; 1073*7c478bd9Sstevel@tonic-gate 1074*7c478bd9Sstevel@tonic-gate } else if (S_ISBLK(statb.st_mode) || S_ISCHR(statb.st_mode)) { 1075*7c478bd9Sstevel@tonic-gate mountp = getmountp(S_ISCHR(statb.st_mode)? unrawname(fs): fs); 1076*7c478bd9Sstevel@tonic-gate if (!mountp) { 1077*7c478bd9Sstevel@tonic-gate return (0); 1078*7c478bd9Sstevel@tonic-gate } 1079*7c478bd9Sstevel@tonic-gate } else { 1080*7c478bd9Sstevel@tonic-gate return (0); 1081*7c478bd9Sstevel@tonic-gate } 1082*7c478bd9Sstevel@tonic-gate 1083*7c478bd9Sstevel@tonic-gate if (elock_combuf == NULL) { 1084*7c478bd9Sstevel@tonic-gate elock_combuf = 1085*7c478bd9Sstevel@tonic-gate (char *)calloc(LOCKFS_MAXCOMMENTLEN, sizeof (char)); 1086*7c478bd9Sstevel@tonic-gate } else { 1087*7c478bd9Sstevel@tonic-gate elock_combuf = 1088*7c478bd9Sstevel@tonic-gate (char *)realloc(elock_combuf, LOCKFS_MAXCOMMENTLEN); 1089*7c478bd9Sstevel@tonic-gate } 1090*7c478bd9Sstevel@tonic-gate 1091*7c478bd9Sstevel@tonic-gate if (elock_combuf == NULL) 1092*7c478bd9Sstevel@tonic-gate return (0); 1093*7c478bd9Sstevel@tonic-gate 1094*7c478bd9Sstevel@tonic-gate bzero((caddr_t)elock_combuf, LOCKFS_MAXCOMMENTLEN); 1095*7c478bd9Sstevel@tonic-gate 1096*7c478bd9Sstevel@tonic-gate elock_mountp = strdup(mountp); 1097*7c478bd9Sstevel@tonic-gate 1098*7c478bd9Sstevel@tonic-gate if (mountfd < 0) { 1099*7c478bd9Sstevel@tonic-gate if ((mountfd = open64(mountp, O_RDONLY)) == -1) 1100*7c478bd9Sstevel@tonic-gate return (0); 1101*7c478bd9Sstevel@tonic-gate } 1102*7c478bd9Sstevel@tonic-gate 1103*7c478bd9Sstevel@tonic-gate if (!lfp) { 1104*7c478bd9Sstevel@tonic-gate lfp = (struct lockfs *)malloc(sizeof (struct lockfs)); 1105*7c478bd9Sstevel@tonic-gate if (!lfp) 1106*7c478bd9Sstevel@tonic-gate return (0); 1107*7c478bd9Sstevel@tonic-gate bzero((caddr_t)lfp, sizeof (struct lockfs)); 1108*7c478bd9Sstevel@tonic-gate } 1109*7c478bd9Sstevel@tonic-gate 1110*7c478bd9Sstevel@tonic-gate lfp->lf_comlen = LOCKFS_MAXCOMMENTLEN; 1111*7c478bd9Sstevel@tonic-gate lfp->lf_comment = elock_combuf; 1112*7c478bd9Sstevel@tonic-gate 1113*7c478bd9Sstevel@tonic-gate if (ioctl(mountfd, _FIOLFSS, lfp) == -1) 1114*7c478bd9Sstevel@tonic-gate return (0); 1115*7c478bd9Sstevel@tonic-gate 1116*7c478bd9Sstevel@tonic-gate return (LOCKFS_IS_ELOCK(lfp)); 1117*7c478bd9Sstevel@tonic-gate } 1118*7c478bd9Sstevel@tonic-gate 1119*7c478bd9Sstevel@tonic-gate static char * 1120*7c478bd9Sstevel@tonic-gate getmountp(char *dev) { 1121*7c478bd9Sstevel@tonic-gate FILE *vfstab; 1122*7c478bd9Sstevel@tonic-gate struct vfstab vfsbuf; 1123*7c478bd9Sstevel@tonic-gate char *mountp; 1124*7c478bd9Sstevel@tonic-gate int rc; 1125*7c478bd9Sstevel@tonic-gate 1126*7c478bd9Sstevel@tonic-gate mountp = NULL; 1127*7c478bd9Sstevel@tonic-gate if ((vfstab = fopen(VFSTAB, "r")) == NULL) { 1128*7c478bd9Sstevel@tonic-gate return (NULL); 1129*7c478bd9Sstevel@tonic-gate } 1130*7c478bd9Sstevel@tonic-gate if ((rc = getvfsspec(vfstab, &vfsbuf, dev)) == 0) { 1131*7c478bd9Sstevel@tonic-gate if (!(mountp = malloc(MAXPATHLEN)) || 1132*7c478bd9Sstevel@tonic-gate vfsbuf.vfs_mountp == NULL) 1133*7c478bd9Sstevel@tonic-gate return (NULL); 1134*7c478bd9Sstevel@tonic-gate strcpy(mountp, vfsbuf.vfs_mountp); 1135*7c478bd9Sstevel@tonic-gate } else if (rc == -1) { 1136*7c478bd9Sstevel@tonic-gate return (NULL); 1137*7c478bd9Sstevel@tonic-gate } 1138*7c478bd9Sstevel@tonic-gate fclose(vfstab); 1139*7c478bd9Sstevel@tonic-gate return (mountp); 1140*7c478bd9Sstevel@tonic-gate } 1141*7c478bd9Sstevel@tonic-gate 1142*7c478bd9Sstevel@tonic-gate do_errorlock(int lock_type) 1143*7c478bd9Sstevel@tonic-gate { 1144*7c478bd9Sstevel@tonic-gate char *buf; 1145*7c478bd9Sstevel@tonic-gate time_t now; 1146*7c478bd9Sstevel@tonic-gate struct tm *local; 1147*7c478bd9Sstevel@tonic-gate int rc = 0; 1148*7c478bd9Sstevel@tonic-gate 1149*7c478bd9Sstevel@tonic-gate if (!elock_combuf) 1150*7c478bd9Sstevel@tonic-gate errexit("do_errorlock(%s, %d): unallocated elock_combuf\n", 1151*7c478bd9Sstevel@tonic-gate elock_mountp? elock_mountp: "<null>", lock_type); 1152*7c478bd9Sstevel@tonic-gate 1153*7c478bd9Sstevel@tonic-gate if (!(buf = (char *)calloc(LOCKFS_MAXCOMMENTLEN, sizeof (char)))) 1154*7c478bd9Sstevel@tonic-gate errexit("Couldn't alloc memory for temp. lock status buffer\n"); 1155*7c478bd9Sstevel@tonic-gate 1156*7c478bd9Sstevel@tonic-gate if (!lfp) { 1157*7c478bd9Sstevel@tonic-gate errexit("do_errorlock(%s, %d): lockfs status unallocated\n", 1158*7c478bd9Sstevel@tonic-gate elock_mountp, lock_type); 1159*7c478bd9Sstevel@tonic-gate } 1160*7c478bd9Sstevel@tonic-gate 1161*7c478bd9Sstevel@tonic-gate bcopy(elock_combuf, buf, LOCKFS_MAXCOMMENTLEN-1); 1162*7c478bd9Sstevel@tonic-gate 1163*7c478bd9Sstevel@tonic-gate switch (lock_type) { 1164*7c478bd9Sstevel@tonic-gate case LOCKFS_ELOCK: 1165*7c478bd9Sstevel@tonic-gate if (time(&now) != (time_t)-1) { 1166*7c478bd9Sstevel@tonic-gate if ((local = localtime(&now)) != NULL) 1167*7c478bd9Sstevel@tonic-gate sprintf(buf, 1168*7c478bd9Sstevel@tonic-gate "%s [pid:%d fsck start:%02d/%02d/%02d %02d:%02d:%02d", 1169*7c478bd9Sstevel@tonic-gate elock_combuf, pid, 1170*7c478bd9Sstevel@tonic-gate local->tm_mon+1, local->tm_mday, 1171*7c478bd9Sstevel@tonic-gate (local->tm_year % 100), local->tm_hour, 1172*7c478bd9Sstevel@tonic-gate local->tm_min, local->tm_sec); 1173*7c478bd9Sstevel@tonic-gate else 1174*7c478bd9Sstevel@tonic-gate sprintf(buf, "%s [fsck pid %d", 1175*7c478bd9Sstevel@tonic-gate elock_combuf, pid); 1176*7c478bd9Sstevel@tonic-gate 1177*7c478bd9Sstevel@tonic-gate } else { 1178*7c478bd9Sstevel@tonic-gate sprintf(buf, "%s [fsck pid %d", elock_combuf, pid); 1179*7c478bd9Sstevel@tonic-gate } 1180*7c478bd9Sstevel@tonic-gate break; 1181*7c478bd9Sstevel@tonic-gate 1182*7c478bd9Sstevel@tonic-gate case LOCKFS_ULOCK: 1183*7c478bd9Sstevel@tonic-gate if (time(&now) != (time_t)-1) { 1184*7c478bd9Sstevel@tonic-gate if ((local = localtime(&now)) != NULL) { 1185*7c478bd9Sstevel@tonic-gate sprintf(buf, 1186*7c478bd9Sstevel@tonic-gate "%s, done:%02d/%02d/%02d %02d:%02d:%02d]", 1187*7c478bd9Sstevel@tonic-gate elock_combuf, 1188*7c478bd9Sstevel@tonic-gate local->tm_mon+1, local->tm_mday, 1189*7c478bd9Sstevel@tonic-gate (local->tm_year % 100), local->tm_hour, 1190*7c478bd9Sstevel@tonic-gate local->tm_min, local->tm_sec); 1191*7c478bd9Sstevel@tonic-gate } else { 1192*7c478bd9Sstevel@tonic-gate sprintf(buf, "%s]", elock_combuf); 1193*7c478bd9Sstevel@tonic-gate } 1194*7c478bd9Sstevel@tonic-gate } else { 1195*7c478bd9Sstevel@tonic-gate sprintf(buf, "%s]", elock_combuf); 1196*7c478bd9Sstevel@tonic-gate } 1197*7c478bd9Sstevel@tonic-gate if ((rc = ioctl(mountfd, _FIOLFSS, lfp)) == -1) { 1198*7c478bd9Sstevel@tonic-gate goto out; 1199*7c478bd9Sstevel@tonic-gate } 1200*7c478bd9Sstevel@tonic-gate break; 1201*7c478bd9Sstevel@tonic-gate 1202*7c478bd9Sstevel@tonic-gate default: 1203*7c478bd9Sstevel@tonic-gate break; 1204*7c478bd9Sstevel@tonic-gate } 1205*7c478bd9Sstevel@tonic-gate 1206*7c478bd9Sstevel@tonic-gate bcopy(buf, elock_combuf, LOCKFS_MAXCOMMENTLEN-1); 1207*7c478bd9Sstevel@tonic-gate 1208*7c478bd9Sstevel@tonic-gate lfp->lf_lock = lock_type; 1209*7c478bd9Sstevel@tonic-gate lfp->lf_comlen = LOCKFS_MAXCOMMENTLEN; 1210*7c478bd9Sstevel@tonic-gate lfp->lf_comment = elock_combuf; 1211*7c478bd9Sstevel@tonic-gate lfp->lf_flags = 0; 1212*7c478bd9Sstevel@tonic-gate errno = 0; 1213*7c478bd9Sstevel@tonic-gate 1214*7c478bd9Sstevel@tonic-gate if ((rc = ioctl(mountfd, _FIOLFS, lfp)) == -1) { 1215*7c478bd9Sstevel@tonic-gate if (errno == EINVAL) { 1216*7c478bd9Sstevel@tonic-gate pwarn("Another fsck active?\n"); 1217*7c478bd9Sstevel@tonic-gate iscorrupt = 0; /* don't go away mad, just go away */ 1218*7c478bd9Sstevel@tonic-gate } else { 1219*7c478bd9Sstevel@tonic-gate pwarn( 1220*7c478bd9Sstevel@tonic-gate "do_errorlock(lock_type:%d, %s) failed: errno:%d\n", 1221*7c478bd9Sstevel@tonic-gate lock_type, elock_combuf, errno); 1222*7c478bd9Sstevel@tonic-gate } 1223*7c478bd9Sstevel@tonic-gate } 1224*7c478bd9Sstevel@tonic-gate out: 1225*7c478bd9Sstevel@tonic-gate if (buf) 1226*7c478bd9Sstevel@tonic-gate free(buf); 1227*7c478bd9Sstevel@tonic-gate 1228*7c478bd9Sstevel@tonic-gate return (rc != -1); 1229*7c478bd9Sstevel@tonic-gate } 1230*7c478bd9Sstevel@tonic-gate 1231*7c478bd9Sstevel@tonic-gate /* 1232*7c478bd9Sstevel@tonic-gate * Shadow inode support. To `register' a shadow with a client is to note 1233*7c478bd9Sstevel@tonic-gate * that an inode (the `client') refers to the shadow. See fsck.h for more 1234*7c478bd9Sstevel@tonic-gate * on how the shadowclientinfo and shadowclients structures are used. 1235*7c478bd9Sstevel@tonic-gate */ 1236*7c478bd9Sstevel@tonic-gate 1237*7c478bd9Sstevel@tonic-gate static struct shadowclients * 1238*7c478bd9Sstevel@tonic-gate newshadowclient(struct shadowclients *prev) 1239*7c478bd9Sstevel@tonic-gate { 1240*7c478bd9Sstevel@tonic-gate struct shadowclients *rc; 1241*7c478bd9Sstevel@tonic-gate 1242*7c478bd9Sstevel@tonic-gate rc = (struct shadowclients *)malloc(sizeof (*rc)); 1243*7c478bd9Sstevel@tonic-gate if (rc == NULL) 1244*7c478bd9Sstevel@tonic-gate errexit("newshadowclient: cannot malloc (1)"); 1245*7c478bd9Sstevel@tonic-gate 1246*7c478bd9Sstevel@tonic-gate rc->next = prev; 1247*7c478bd9Sstevel@tonic-gate rc->nclients = 0; 1248*7c478bd9Sstevel@tonic-gate 1249*7c478bd9Sstevel@tonic-gate rc->client = (ino_t *) 1250*7c478bd9Sstevel@tonic-gate malloc(sizeof (ino_t) * maxshadowclients); 1251*7c478bd9Sstevel@tonic-gate if (rc->client == NULL) 1252*7c478bd9Sstevel@tonic-gate errexit("newshadowclient: cannot malloc (2)"); 1253*7c478bd9Sstevel@tonic-gate 1254*7c478bd9Sstevel@tonic-gate return (rc); 1255*7c478bd9Sstevel@tonic-gate } 1256*7c478bd9Sstevel@tonic-gate 1257*7c478bd9Sstevel@tonic-gate void 1258*7c478bd9Sstevel@tonic-gate registershadowclient(ino_t shadow, ino_t client, struct shadowclientinfo **info) 1259*7c478bd9Sstevel@tonic-gate { 1260*7c478bd9Sstevel@tonic-gate struct shadowclientinfo *sci; 1261*7c478bd9Sstevel@tonic-gate struct shadowclients *scc; 1262*7c478bd9Sstevel@tonic-gate 1263*7c478bd9Sstevel@tonic-gate for (sci = *info; sci; sci = sci->next) 1264*7c478bd9Sstevel@tonic-gate if (sci->shadow == shadow) 1265*7c478bd9Sstevel@tonic-gate break; 1266*7c478bd9Sstevel@tonic-gate if (sci == NULL) { 1267*7c478bd9Sstevel@tonic-gate sci = (struct shadowclientinfo *)malloc(sizeof (*sci)); 1268*7c478bd9Sstevel@tonic-gate if (sci == NULL) 1269*7c478bd9Sstevel@tonic-gate errexit("registershadowclient: cannot malloc"); 1270*7c478bd9Sstevel@tonic-gate sci->next = *info; 1271*7c478bd9Sstevel@tonic-gate *info = sci; 1272*7c478bd9Sstevel@tonic-gate sci->shadow = shadow; 1273*7c478bd9Sstevel@tonic-gate sci->totalClients = 0; 1274*7c478bd9Sstevel@tonic-gate sci->clients = newshadowclient(NULL); 1275*7c478bd9Sstevel@tonic-gate } 1276*7c478bd9Sstevel@tonic-gate 1277*7c478bd9Sstevel@tonic-gate sci->totalClients++; 1278*7c478bd9Sstevel@tonic-gate scc = sci->clients; 1279*7c478bd9Sstevel@tonic-gate if (scc->nclients >= maxshadowclients) { 1280*7c478bd9Sstevel@tonic-gate scc = newshadowclient(sci->clients); 1281*7c478bd9Sstevel@tonic-gate sci->clients = scc; 1282*7c478bd9Sstevel@tonic-gate } 1283*7c478bd9Sstevel@tonic-gate 1284*7c478bd9Sstevel@tonic-gate scc->client[scc->nclients++] = client; 1285*7c478bd9Sstevel@tonic-gate } 1286*7c478bd9Sstevel@tonic-gate 1287*7c478bd9Sstevel@tonic-gate /* 1288*7c478bd9Sstevel@tonic-gate * Allocate more buffer as need arises but allocate one at a time. 1289*7c478bd9Sstevel@tonic-gate * This is done to make sure that fsck does not exit with error if it 1290*7c478bd9Sstevel@tonic-gate * needs more buffer to complete it's task. 1291*7c478bd9Sstevel@tonic-gate */ 1292*7c478bd9Sstevel@tonic-gate static struct bufarea * 1293*7c478bd9Sstevel@tonic-gate alloc_bufarea() 1294*7c478bd9Sstevel@tonic-gate { 1295*7c478bd9Sstevel@tonic-gate struct bufarea *bp; 1296*7c478bd9Sstevel@tonic-gate char *bufp; 1297*7c478bd9Sstevel@tonic-gate 1298*7c478bd9Sstevel@tonic-gate bp = (struct bufarea *)malloc(sizeof (struct bufarea)); 1299*7c478bd9Sstevel@tonic-gate bufp = malloc((unsigned int)sblock.fs_bsize); 1300*7c478bd9Sstevel@tonic-gate if (bp == NULL || bufp == NULL) { 1301*7c478bd9Sstevel@tonic-gate if (bp) 1302*7c478bd9Sstevel@tonic-gate free((char *)bp); 1303*7c478bd9Sstevel@tonic-gate if (bufp) 1304*7c478bd9Sstevel@tonic-gate free(bufp); 1305*7c478bd9Sstevel@tonic-gate return (NULL); 1306*7c478bd9Sstevel@tonic-gate } 1307*7c478bd9Sstevel@tonic-gate bp->b_un.b_buf = bufp; 1308*7c478bd9Sstevel@tonic-gate bp->b_prev = &bufhead; 1309*7c478bd9Sstevel@tonic-gate bp->b_next = bufhead.b_next; 1310*7c478bd9Sstevel@tonic-gate bufhead.b_next->b_prev = bp; 1311*7c478bd9Sstevel@tonic-gate bufhead.b_next = bp; 1312*7c478bd9Sstevel@tonic-gate initbarea(bp); 1313*7c478bd9Sstevel@tonic-gate bufhead.b_size++; 1314*7c478bd9Sstevel@tonic-gate return (bp); 1315*7c478bd9Sstevel@tonic-gate } 1316