17c478bd9Sstevel@tonic-gate /* 2*fe0e7ec4Smaheshvs * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 77c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 87c478bd9Sstevel@tonic-gate 97c478bd9Sstevel@tonic-gate /* 107c478bd9Sstevel@tonic-gate * Copyright (c) 1980, 1986, 1990 The Regents of the University of California. 117c478bd9Sstevel@tonic-gate * All rights reserved. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted 147c478bd9Sstevel@tonic-gate * provided that: (1) source distributions retain this entire copyright 157c478bd9Sstevel@tonic-gate * notice and comment, and (2) distributions including binaries display 167c478bd9Sstevel@tonic-gate * the following acknowledgement: ``This product includes software 177c478bd9Sstevel@tonic-gate * developed by the University of California, Berkeley and its contributors'' 187c478bd9Sstevel@tonic-gate * in the documentation or other materials provided with the distribution 197c478bd9Sstevel@tonic-gate * and in all advertising materials mentioning features or use of this 207c478bd9Sstevel@tonic-gate * software. Neither the name of the University nor the names of its 217c478bd9Sstevel@tonic-gate * contributors may be used to endorse or promote products derived 227c478bd9Sstevel@tonic-gate * from this software without specific prior written permission. 237c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 247c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 257c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <stdio.h> 317c478bd9Sstevel@tonic-gate #include <fcntl.h> 327c478bd9Sstevel@tonic-gate #include <errno.h> 337c478bd9Sstevel@tonic-gate #include <unistd.h> 347c478bd9Sstevel@tonic-gate #include <stdlib.h> 35*fe0e7ec4Smaheshvs #include <stdarg.h> 367c478bd9Sstevel@tonic-gate #include <fcntl.h> 377c478bd9Sstevel@tonic-gate #include <string.h> 387c478bd9Sstevel@tonic-gate #include <strings.h> 397c478bd9Sstevel@tonic-gate #include <ctype.h> 407c478bd9Sstevel@tonic-gate #include <malloc.h> 417c478bd9Sstevel@tonic-gate #include <signal.h> 427c478bd9Sstevel@tonic-gate #include <sys/param.h> 437c478bd9Sstevel@tonic-gate #include <sys/types.h> 447c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 457c478bd9Sstevel@tonic-gate #include <sys/filio.h> 467c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 477c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 487c478bd9Sstevel@tonic-gate #include <sys/types.h> 497c478bd9Sstevel@tonic-gate #include <sys/stat.h> 507c478bd9Sstevel@tonic-gate #include <sys/vfstab.h> 517c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 527c478bd9Sstevel@tonic-gate #include <sys/fs/udf_volume.h> 537c478bd9Sstevel@tonic-gate #include "fsck.h" 547c478bd9Sstevel@tonic-gate #include <sys/lockfs.h> 557c478bd9Sstevel@tonic-gate #include <locale.h> 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate extern int32_t verifytag(struct tag *, uint32_t, struct tag *, int); 587c478bd9Sstevel@tonic-gate extern char *tagerrs[]; 597c478bd9Sstevel@tonic-gate extern void maketag(struct tag *, struct tag *); 607c478bd9Sstevel@tonic-gate extern char *hasvfsopt(struct vfstab *, char *); 617c478bd9Sstevel@tonic-gate static struct bufarea *getdatablk(daddr_t, long); 627c478bd9Sstevel@tonic-gate static struct bufarea *getblk(struct bufarea *, daddr_t, long); 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate void flush(int32_t, struct bufarea *); 657c478bd9Sstevel@tonic-gate int32_t bread(int32_t, char *, daddr_t, long); 667c478bd9Sstevel@tonic-gate void bwrite(int, char *, daddr_t, long); 677c478bd9Sstevel@tonic-gate static int32_t getline(FILE *, char *, int32_t); 68*fe0e7ec4Smaheshvs void errexit(char *, ...) __NORETURN; 697c478bd9Sstevel@tonic-gate static long diskreads, totalreads; /* Disk cache statistics */ 707c478bd9Sstevel@tonic-gate offset_t llseek(); 717c478bd9Sstevel@tonic-gate extern unsigned int largefile_count; 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate /* 747c478bd9Sstevel@tonic-gate * An unexpected inconsistency occured. 757c478bd9Sstevel@tonic-gate * Die if preening, otherwise just print message and continue. 767c478bd9Sstevel@tonic-gate */ 777c478bd9Sstevel@tonic-gate /* VARARGS1 */ 787c478bd9Sstevel@tonic-gate void 79*fe0e7ec4Smaheshvs pfatal(char *fmt, ...) 807c478bd9Sstevel@tonic-gate { 81*fe0e7ec4Smaheshvs va_list args; 82*fe0e7ec4Smaheshvs va_start(args, fmt); 837c478bd9Sstevel@tonic-gate if (preen) { 847c478bd9Sstevel@tonic-gate (void) printf("%s: ", devname); 85*fe0e7ec4Smaheshvs (void) vprintf(fmt, args); 867c478bd9Sstevel@tonic-gate (void) printf("\n"); 877c478bd9Sstevel@tonic-gate (void) printf( 887c478bd9Sstevel@tonic-gate gettext("%s: UNEXPECTED INCONSISTENCY; RUN fsck " 897c478bd9Sstevel@tonic-gate "MANUALLY.\n"), devname); 90*fe0e7ec4Smaheshvs va_end(args); 917c478bd9Sstevel@tonic-gate exit(36); 927c478bd9Sstevel@tonic-gate } 93*fe0e7ec4Smaheshvs (void) vprintf(fmt, args); 94*fe0e7ec4Smaheshvs va_end(args); 957c478bd9Sstevel@tonic-gate } 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate /* 987c478bd9Sstevel@tonic-gate * Pwarn just prints a message when not preening, 997c478bd9Sstevel@tonic-gate * or a warning (preceded by filename) when preening. 1007c478bd9Sstevel@tonic-gate */ 1017c478bd9Sstevel@tonic-gate /* VARARGS1 */ 1027c478bd9Sstevel@tonic-gate void 103*fe0e7ec4Smaheshvs pwarn(char *fmt, ...) 1047c478bd9Sstevel@tonic-gate { 105*fe0e7ec4Smaheshvs va_list args; 106*fe0e7ec4Smaheshvs va_start(args, fmt); 1077c478bd9Sstevel@tonic-gate if (preen) 1087c478bd9Sstevel@tonic-gate (void) printf("%s: ", devname); 109*fe0e7ec4Smaheshvs (void) vprintf(fmt, args); 110*fe0e7ec4Smaheshvs va_end(args); 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate /* VARARGS1 */ 1157c478bd9Sstevel@tonic-gate void 116*fe0e7ec4Smaheshvs errexit(char *fmt, ...) 1177c478bd9Sstevel@tonic-gate { 118*fe0e7ec4Smaheshvs va_list args; 119*fe0e7ec4Smaheshvs va_start(args, fmt); 120*fe0e7ec4Smaheshvs (void) vprintf(fmt, args); 121*fe0e7ec4Smaheshvs va_end(args); 1227c478bd9Sstevel@tonic-gate exit(39); 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate void 1267c478bd9Sstevel@tonic-gate markbusy(daddr_t block, long count) 1277c478bd9Sstevel@tonic-gate { 1287c478bd9Sstevel@tonic-gate register int i; 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate count = roundup(count, secsize) / secsize; 1317c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++, block++) { 1327c478bd9Sstevel@tonic-gate if ((unsigned)block > part_len) { 1337c478bd9Sstevel@tonic-gate pwarn(gettext("Block %lx out of range\n"), block); 1347c478bd9Sstevel@tonic-gate break; 1357c478bd9Sstevel@tonic-gate } 1367c478bd9Sstevel@tonic-gate if (testbusy(block)) 1377c478bd9Sstevel@tonic-gate pwarn(gettext("Dup block %lx\n"), block); 1387c478bd9Sstevel@tonic-gate else { 1397c478bd9Sstevel@tonic-gate n_blks++; 1407c478bd9Sstevel@tonic-gate setbusy(block); 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate void 1467c478bd9Sstevel@tonic-gate printfree() 1477c478bd9Sstevel@tonic-gate { 1487c478bd9Sstevel@tonic-gate int i, startfree, endfree; 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate startfree = -1; 1517c478bd9Sstevel@tonic-gate for (i = 0; i < part_len; i++) { 1527c478bd9Sstevel@tonic-gate if (!testbusy(i)) { 1537c478bd9Sstevel@tonic-gate if (startfree <= 0) 1547c478bd9Sstevel@tonic-gate startfree = i; 1557c478bd9Sstevel@tonic-gate endfree = i; 1567c478bd9Sstevel@tonic-gate } else if (startfree >= 0) { 1577c478bd9Sstevel@tonic-gate (void) printf("free: %x-%x\n", startfree, endfree - 1); 1587c478bd9Sstevel@tonic-gate startfree = -1; 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate if (startfree >= 0) { 1627c478bd9Sstevel@tonic-gate (void) printf("free: %x-%x\n", startfree, endfree); 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate struct bufarea * 1677c478bd9Sstevel@tonic-gate getfilentry(uint32_t block, int len) 1687c478bd9Sstevel@tonic-gate { 1697c478bd9Sstevel@tonic-gate struct bufarea *bp; 1707c478bd9Sstevel@tonic-gate struct file_entry *fp; 1717c478bd9Sstevel@tonic-gate int err; 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate if (len > fsbsize) { 1747c478bd9Sstevel@tonic-gate (void) printf(gettext("File entry at %x is too long " 1757c478bd9Sstevel@tonic-gate "(%d bytes)\n"), block, len); 1767c478bd9Sstevel@tonic-gate len = fsbsize; 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate bp = getdatablk((daddr_t)(block + part_start), fsbsize); 1797c478bd9Sstevel@tonic-gate if (bp->b_errs) { 1807c478bd9Sstevel@tonic-gate bp->b_flags &= ~B_INUSE; 1817c478bd9Sstevel@tonic-gate return (NULL); 1827c478bd9Sstevel@tonic-gate } 1837c478bd9Sstevel@tonic-gate /* LINTED */ 1847c478bd9Sstevel@tonic-gate fp = (struct file_entry *)bp->b_un.b_buf; 1857c478bd9Sstevel@tonic-gate err = verifytag(&fp->fe_tag, block, &fp->fe_tag, UD_FILE_ENTRY); 1867c478bd9Sstevel@tonic-gate if (err) { 1877c478bd9Sstevel@tonic-gate (void) printf(gettext("Tag error %s or bad file entry, " 1887c478bd9Sstevel@tonic-gate "tag=%d\n"), tagerrs[err], fp->fe_tag.tag_id); 1897c478bd9Sstevel@tonic-gate bp->b_flags &= ~B_INUSE; 1907c478bd9Sstevel@tonic-gate return (NULL); 1917c478bd9Sstevel@tonic-gate } 1927c478bd9Sstevel@tonic-gate return (bp); 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate void 1967c478bd9Sstevel@tonic-gate putfilentry(struct bufarea *bp) 1977c478bd9Sstevel@tonic-gate { 1987c478bd9Sstevel@tonic-gate struct file_entry *fp; 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate /* LINTED */ 2017c478bd9Sstevel@tonic-gate fp = (struct file_entry *)bp->b_un.b_buf; 2027c478bd9Sstevel@tonic-gate maketag(&fp->fe_tag, &fp->fe_tag); 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate int32_t 2077c478bd9Sstevel@tonic-gate reply(char *question) 2087c478bd9Sstevel@tonic-gate { 2097c478bd9Sstevel@tonic-gate char line[80]; 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate if (preen) 2127c478bd9Sstevel@tonic-gate pfatal(gettext("INTERNAL ERROR: GOT TO reply()")); 2137c478bd9Sstevel@tonic-gate (void) printf("\n%s? ", question); 2147c478bd9Sstevel@tonic-gate if (nflag || fswritefd < 0) { 2157c478bd9Sstevel@tonic-gate (void) printf(gettext(" no\n\n")); 2167c478bd9Sstevel@tonic-gate iscorrupt = 1; /* known to be corrupt */ 2177c478bd9Sstevel@tonic-gate return (0); 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate if (yflag) { 2207c478bd9Sstevel@tonic-gate (void) printf(gettext(" yes\n\n")); 2217c478bd9Sstevel@tonic-gate return (1); 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate if (getline(stdin, line, sizeof (line)) == EOF) 2247c478bd9Sstevel@tonic-gate errexit("\n"); 2257c478bd9Sstevel@tonic-gate (void) printf("\n"); 2267c478bd9Sstevel@tonic-gate if (line[0] == 'y' || line[0] == 'Y') 2277c478bd9Sstevel@tonic-gate return (1); 2287c478bd9Sstevel@tonic-gate else { 2297c478bd9Sstevel@tonic-gate iscorrupt = 1; /* known to be corrupt */ 2307c478bd9Sstevel@tonic-gate return (0); 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate int32_t 2357c478bd9Sstevel@tonic-gate getline(FILE *fp, char *loc, int32_t maxlen) 2367c478bd9Sstevel@tonic-gate { 237*fe0e7ec4Smaheshvs int n; 2387c478bd9Sstevel@tonic-gate register char *p, *lastloc; 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate p = loc; 2417c478bd9Sstevel@tonic-gate lastloc = &p[maxlen-1]; 2427c478bd9Sstevel@tonic-gate while ((n = getc(fp)) != '\n') { 2437c478bd9Sstevel@tonic-gate if (n == EOF) 2447c478bd9Sstevel@tonic-gate return (EOF); 2457c478bd9Sstevel@tonic-gate if (!isspace(n) && p < lastloc) 2467c478bd9Sstevel@tonic-gate *p++ = n; 2477c478bd9Sstevel@tonic-gate } 2487c478bd9Sstevel@tonic-gate *p = 0; 2497c478bd9Sstevel@tonic-gate return (p - loc); 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate /* 2527c478bd9Sstevel@tonic-gate * Malloc buffers and set up cache. 2537c478bd9Sstevel@tonic-gate */ 2547c478bd9Sstevel@tonic-gate void 2557c478bd9Sstevel@tonic-gate bufinit() 2567c478bd9Sstevel@tonic-gate { 2577c478bd9Sstevel@tonic-gate register struct bufarea *bp; 2587c478bd9Sstevel@tonic-gate long bufcnt, i; 2597c478bd9Sstevel@tonic-gate char *bufp; 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate bufp = malloc((unsigned int)fsbsize); 2627c478bd9Sstevel@tonic-gate if (bufp == 0) 2637c478bd9Sstevel@tonic-gate errexit(gettext("cannot allocate buffer pool\n")); 2647c478bd9Sstevel@tonic-gate bufhead.b_next = bufhead.b_prev = &bufhead; 2657c478bd9Sstevel@tonic-gate bufcnt = MAXBUFSPACE / fsbsize; 2667c478bd9Sstevel@tonic-gate if (bufcnt < MINBUFS) 2677c478bd9Sstevel@tonic-gate bufcnt = MINBUFS; 2687c478bd9Sstevel@tonic-gate for (i = 0; i < bufcnt; i++) { 2697c478bd9Sstevel@tonic-gate bp = (struct bufarea *)malloc(sizeof (struct bufarea)); 2707c478bd9Sstevel@tonic-gate bufp = malloc((unsigned int)fsbsize); 2717c478bd9Sstevel@tonic-gate if (bp == NULL || bufp == NULL) { 2727c478bd9Sstevel@tonic-gate if (i >= MINBUFS) 2737c478bd9Sstevel@tonic-gate break; 2747c478bd9Sstevel@tonic-gate errexit(gettext("cannot allocate buffer pool\n")); 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate bp->b_un.b_buf = bufp; 2777c478bd9Sstevel@tonic-gate bp->b_prev = &bufhead; 2787c478bd9Sstevel@tonic-gate bp->b_next = bufhead.b_next; 2797c478bd9Sstevel@tonic-gate bufhead.b_next->b_prev = bp; 2807c478bd9Sstevel@tonic-gate bufhead.b_next = bp; 2817c478bd9Sstevel@tonic-gate initbarea(bp); 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate bufhead.b_size = i; /* save number of buffers */ 2847c478bd9Sstevel@tonic-gate pbp = pdirbp = NULL; 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate /* 2887c478bd9Sstevel@tonic-gate * Manage a cache of directory blocks. 2897c478bd9Sstevel@tonic-gate */ 2907c478bd9Sstevel@tonic-gate static struct bufarea * 2917c478bd9Sstevel@tonic-gate getdatablk(daddr_t blkno, long size) 2927c478bd9Sstevel@tonic-gate { 2937c478bd9Sstevel@tonic-gate register struct bufarea *bp; 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next) 2967c478bd9Sstevel@tonic-gate if (bp->b_bno == fsbtodb(blkno)) 2977c478bd9Sstevel@tonic-gate goto foundit; 2987c478bd9Sstevel@tonic-gate for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev) 2997c478bd9Sstevel@tonic-gate if ((bp->b_flags & B_INUSE) == 0) 3007c478bd9Sstevel@tonic-gate break; 3017c478bd9Sstevel@tonic-gate if (bp == &bufhead) 3027c478bd9Sstevel@tonic-gate errexit(gettext("deadlocked buffer pool\n")); 3037c478bd9Sstevel@tonic-gate (void) getblk(bp, blkno, size); 3047c478bd9Sstevel@tonic-gate /* fall through */ 3057c478bd9Sstevel@tonic-gate foundit: 3067c478bd9Sstevel@tonic-gate totalreads++; 3077c478bd9Sstevel@tonic-gate bp->b_prev->b_next = bp->b_next; 3087c478bd9Sstevel@tonic-gate bp->b_next->b_prev = bp->b_prev; 3097c478bd9Sstevel@tonic-gate bp->b_prev = &bufhead; 3107c478bd9Sstevel@tonic-gate bp->b_next = bufhead.b_next; 3117c478bd9Sstevel@tonic-gate bufhead.b_next->b_prev = bp; 3127c478bd9Sstevel@tonic-gate bufhead.b_next = bp; 3137c478bd9Sstevel@tonic-gate bp->b_flags |= B_INUSE; 3147c478bd9Sstevel@tonic-gate return (bp); 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate static struct bufarea * 3187c478bd9Sstevel@tonic-gate getblk(struct bufarea *bp, daddr_t blk, long size) 3197c478bd9Sstevel@tonic-gate { 3207c478bd9Sstevel@tonic-gate daddr_t dblk; 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate dblk = fsbtodb(blk); 3237c478bd9Sstevel@tonic-gate if (bp->b_bno == dblk) 3247c478bd9Sstevel@tonic-gate return (bp); 3257c478bd9Sstevel@tonic-gate flush(fswritefd, bp); 3267c478bd9Sstevel@tonic-gate diskreads++; 3277c478bd9Sstevel@tonic-gate bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, dblk, size); 3287c478bd9Sstevel@tonic-gate bp->b_bno = dblk; 3297c478bd9Sstevel@tonic-gate bp->b_size = size; 3307c478bd9Sstevel@tonic-gate return (bp); 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate void 3347c478bd9Sstevel@tonic-gate flush(int32_t fd, struct bufarea *bp) 3357c478bd9Sstevel@tonic-gate { 3367c478bd9Sstevel@tonic-gate if (!bp->b_dirty) 3377c478bd9Sstevel@tonic-gate return; 3387c478bd9Sstevel@tonic-gate if (bp->b_errs != 0) 3397c478bd9Sstevel@tonic-gate pfatal(gettext("WRITING ZERO'ED BLOCK %d TO DISK\n"), 3407c478bd9Sstevel@tonic-gate bp->b_bno); 3417c478bd9Sstevel@tonic-gate bp->b_dirty = 0; 3427c478bd9Sstevel@tonic-gate bp->b_errs = 0; 3437c478bd9Sstevel@tonic-gate bwrite(fd, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size); 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate static void 3477c478bd9Sstevel@tonic-gate rwerror(char *mesg, daddr_t blk) 3487c478bd9Sstevel@tonic-gate { 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate if (preen == 0) 3517c478bd9Sstevel@tonic-gate (void) printf("\n"); 3527c478bd9Sstevel@tonic-gate pfatal(gettext("CANNOT %s: BLK %ld"), mesg, blk); 3537c478bd9Sstevel@tonic-gate if (reply(gettext("CONTINUE")) == 0) 3547c478bd9Sstevel@tonic-gate errexit(gettext("Program terminated\n")); 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate void 3587c478bd9Sstevel@tonic-gate ckfini() 3597c478bd9Sstevel@tonic-gate { 3607c478bd9Sstevel@tonic-gate struct bufarea *bp, *nbp; 3617c478bd9Sstevel@tonic-gate int cnt = 0; 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) { 3647c478bd9Sstevel@tonic-gate cnt++; 3657c478bd9Sstevel@tonic-gate flush(fswritefd, bp); 3667c478bd9Sstevel@tonic-gate nbp = bp->b_prev; 3677c478bd9Sstevel@tonic-gate free(bp->b_un.b_buf); 3687c478bd9Sstevel@tonic-gate free((char *)bp); 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate pbp = pdirbp = NULL; 3717c478bd9Sstevel@tonic-gate if (bufhead.b_size != cnt) 3727c478bd9Sstevel@tonic-gate errexit(gettext("Panic: lost %d buffers\n"), 3737c478bd9Sstevel@tonic-gate bufhead.b_size - cnt); 3747c478bd9Sstevel@tonic-gate if (debug) 3757c478bd9Sstevel@tonic-gate (void) printf("cache missed %ld of %ld (%ld%%)\n", 3767c478bd9Sstevel@tonic-gate diskreads, totalreads, 3777c478bd9Sstevel@tonic-gate totalreads ? diskreads * 100 / totalreads : 0); 3787c478bd9Sstevel@tonic-gate (void) close(fsreadfd); 3797c478bd9Sstevel@tonic-gate (void) close(fswritefd); 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate int32_t 3837c478bd9Sstevel@tonic-gate bread(int fd, char *buf, daddr_t blk, long size) 3847c478bd9Sstevel@tonic-gate { 3857c478bd9Sstevel@tonic-gate char *cp; 3867c478bd9Sstevel@tonic-gate int i, errs; 3877c478bd9Sstevel@tonic-gate offset_t offset = ldbtob(blk); 3887c478bd9Sstevel@tonic-gate offset_t addr; 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate if (llseek(fd, offset, 0) < 0) 3917c478bd9Sstevel@tonic-gate rwerror(gettext("SEEK"), blk); 3927c478bd9Sstevel@tonic-gate else if (read(fd, buf, (int)size) == size) 3937c478bd9Sstevel@tonic-gate return (0); 3947c478bd9Sstevel@tonic-gate rwerror(gettext("READ"), blk); 3957c478bd9Sstevel@tonic-gate if (llseek(fd, offset, 0) < 0) 3967c478bd9Sstevel@tonic-gate rwerror(gettext("SEEK"), blk); 3977c478bd9Sstevel@tonic-gate errs = 0; 3987c478bd9Sstevel@tonic-gate bzero(buf, (int)size); 3997c478bd9Sstevel@tonic-gate pwarn(gettext("THE FOLLOWING SECTORS COULD NOT BE READ:")); 4007c478bd9Sstevel@tonic-gate for (cp = buf, i = 0; i < btodb(size); i++, cp += DEV_BSIZE) { 4017c478bd9Sstevel@tonic-gate addr = ldbtob(blk + i); 4027c478bd9Sstevel@tonic-gate if (llseek(fd, addr, SEEK_CUR) < 0 || 4037c478bd9Sstevel@tonic-gate read(fd, cp, (int)secsize) < 0) { 4047c478bd9Sstevel@tonic-gate (void) printf(" %ld", blk + i); 4057c478bd9Sstevel@tonic-gate errs++; 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate (void) printf("\n"); 4097c478bd9Sstevel@tonic-gate return (errs); 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate void 4137c478bd9Sstevel@tonic-gate bwrite(int fd, char *buf, daddr_t blk, long size) 4147c478bd9Sstevel@tonic-gate { 4157c478bd9Sstevel@tonic-gate int i, n; 4167c478bd9Sstevel@tonic-gate char *cp; 4177c478bd9Sstevel@tonic-gate offset_t offset = ldbtob(blk); 4187c478bd9Sstevel@tonic-gate offset_t addr; 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate if (fd < 0) 4217c478bd9Sstevel@tonic-gate return; 4227c478bd9Sstevel@tonic-gate if (llseek(fd, offset, 0) < 0) 4237c478bd9Sstevel@tonic-gate rwerror(gettext("SEEK"), blk); 4247c478bd9Sstevel@tonic-gate else if (write(fd, buf, (int)size) == size) { 4257c478bd9Sstevel@tonic-gate fsmodified = 1; 4267c478bd9Sstevel@tonic-gate return; 4277c478bd9Sstevel@tonic-gate } 4287c478bd9Sstevel@tonic-gate rwerror(gettext("WRITE"), blk); 4297c478bd9Sstevel@tonic-gate if (llseek(fd, offset, 0) < 0) 4307c478bd9Sstevel@tonic-gate rwerror(gettext("SEEK"), blk); 4317c478bd9Sstevel@tonic-gate pwarn(gettext("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:")); 4327c478bd9Sstevel@tonic-gate for (cp = buf, i = 0; i < btodb(size); i++, cp += DEV_BSIZE) { 4337c478bd9Sstevel@tonic-gate n = 0; 4347c478bd9Sstevel@tonic-gate addr = ldbtob(blk + i); 4357c478bd9Sstevel@tonic-gate if (llseek(fd, addr, SEEK_CUR) < 0 || 4367c478bd9Sstevel@tonic-gate (n = write(fd, cp, DEV_BSIZE)) < 0) { 4377c478bd9Sstevel@tonic-gate (void) printf(" %ld", blk + i); 4387c478bd9Sstevel@tonic-gate } else if (n > 0) { 4397c478bd9Sstevel@tonic-gate fsmodified = 1; 4407c478bd9Sstevel@tonic-gate } 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate (void) printf("\n"); 4447c478bd9Sstevel@tonic-gate } 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate void 4477c478bd9Sstevel@tonic-gate catch() 4487c478bd9Sstevel@tonic-gate { 4497c478bd9Sstevel@tonic-gate ckfini(); 4507c478bd9Sstevel@tonic-gate exit(37); 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate /* 4547c478bd9Sstevel@tonic-gate * When preening, allow a single quit to signal 4557c478bd9Sstevel@tonic-gate * a special exit after filesystem checks complete 4567c478bd9Sstevel@tonic-gate * so that reboot sequence may be interrupted. 4577c478bd9Sstevel@tonic-gate */ 4587c478bd9Sstevel@tonic-gate void 4597c478bd9Sstevel@tonic-gate catchquit() 4607c478bd9Sstevel@tonic-gate { 461*fe0e7ec4Smaheshvs extern int returntosingle; 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate (void) printf(gettext("returning to single-user after filesystem " 4647c478bd9Sstevel@tonic-gate "check\n")); 4657c478bd9Sstevel@tonic-gate returntosingle = 1; 4667c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_DFL); 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate /* 4707c478bd9Sstevel@tonic-gate * determine whether an inode should be fixed. 4717c478bd9Sstevel@tonic-gate */ 4727c478bd9Sstevel@tonic-gate /* ARGSUSED1 */ 4737c478bd9Sstevel@tonic-gate int32_t 4747c478bd9Sstevel@tonic-gate dofix(struct inodesc *idesc, char *msg) 4757c478bd9Sstevel@tonic-gate { 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate switch (idesc->id_fix) { 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate case DONTKNOW: 4807c478bd9Sstevel@tonic-gate pwarn(msg); 4817c478bd9Sstevel@tonic-gate if (preen) { 4827c478bd9Sstevel@tonic-gate (void) printf(gettext(" (SALVAGED)\n")); 4837c478bd9Sstevel@tonic-gate idesc->id_fix = FIX; 4847c478bd9Sstevel@tonic-gate return (ALTERED); 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate if (reply(gettext("SALVAGE")) == 0) { 4877c478bd9Sstevel@tonic-gate idesc->id_fix = NOFIX; 4887c478bd9Sstevel@tonic-gate return (0); 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate idesc->id_fix = FIX; 4917c478bd9Sstevel@tonic-gate return (ALTERED); 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate case FIX: 4947c478bd9Sstevel@tonic-gate return (ALTERED); 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate case NOFIX: 4977c478bd9Sstevel@tonic-gate return (0); 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate default: 5007c478bd9Sstevel@tonic-gate errexit(gettext("UNKNOWN INODESC FIX MODE %d\n"), 5017c478bd9Sstevel@tonic-gate idesc->id_fix); 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate /* NOTREACHED */ 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate /* 5077c478bd9Sstevel@tonic-gate * Check to see if unraw version of name is already mounted. 5087c478bd9Sstevel@tonic-gate * Since we do not believe /etc/mnttab, we stat the mount point 5097c478bd9Sstevel@tonic-gate * to see if it is really looks mounted. 5107c478bd9Sstevel@tonic-gate */ 511*fe0e7ec4Smaheshvs int 5127c478bd9Sstevel@tonic-gate mounted(char *name) 5137c478bd9Sstevel@tonic-gate { 5147c478bd9Sstevel@tonic-gate int found = 0; 5157c478bd9Sstevel@tonic-gate struct mnttab mnt; 5167c478bd9Sstevel@tonic-gate FILE *mnttab; 5177c478bd9Sstevel@tonic-gate struct stat device_stat, mount_stat; 5187c478bd9Sstevel@tonic-gate char *blkname, *unrawname(); 5197c478bd9Sstevel@tonic-gate int err; 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate mnttab = fopen(MNTTAB, "r"); 5227c478bd9Sstevel@tonic-gate if (mnttab == NULL) { 5237c478bd9Sstevel@tonic-gate (void) printf(gettext("can't open %s\n"), MNTTAB); 5247c478bd9Sstevel@tonic-gate return (0); 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate blkname = unrawname(name); 5277c478bd9Sstevel@tonic-gate while ((getmntent(mnttab, &mnt)) == NULL) { 5287c478bd9Sstevel@tonic-gate if (strcmp(mnt.mnt_fstype, MNTTYPE_UDFS) != 0) { 5297c478bd9Sstevel@tonic-gate continue; 5307c478bd9Sstevel@tonic-gate } 5317c478bd9Sstevel@tonic-gate if (strcmp(blkname, mnt.mnt_special) == 0) { 5327c478bd9Sstevel@tonic-gate err = stat(mnt.mnt_mountp, &mount_stat); 5337c478bd9Sstevel@tonic-gate err |= stat(mnt.mnt_special, &device_stat); 5347c478bd9Sstevel@tonic-gate if (err < 0) 5357c478bd9Sstevel@tonic-gate continue; 5367c478bd9Sstevel@tonic-gate if (device_stat.st_rdev == mount_stat.st_dev) { 5377c478bd9Sstevel@tonic-gate (void) strncpy(mnt.mnt_mountp, mountpoint, 5387c478bd9Sstevel@tonic-gate sizeof (mountpoint)); 5397c478bd9Sstevel@tonic-gate if (hasmntopt(&mnt, MNTOPT_RO) != 0) 5407c478bd9Sstevel@tonic-gate found = 2; /* mounted as RO */ 5417c478bd9Sstevel@tonic-gate else 5427c478bd9Sstevel@tonic-gate found = 1; /* mounted as R/W */ 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate break; 5457c478bd9Sstevel@tonic-gate } 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate (void) fclose(mnttab); 5487c478bd9Sstevel@tonic-gate return (found); 5497c478bd9Sstevel@tonic-gate } 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate /* 5527c478bd9Sstevel@tonic-gate * Check to see if name corresponds to an entry in vfstab, and that the entry 5537c478bd9Sstevel@tonic-gate * does not have option ro. 5547c478bd9Sstevel@tonic-gate */ 555*fe0e7ec4Smaheshvs int 5567c478bd9Sstevel@tonic-gate writable(char *name) 5577c478bd9Sstevel@tonic-gate { 5587c478bd9Sstevel@tonic-gate int rw = 1; 5597c478bd9Sstevel@tonic-gate struct vfstab vfsbuf; 5607c478bd9Sstevel@tonic-gate FILE *vfstab; 5617c478bd9Sstevel@tonic-gate char *blkname, *unrawname(); 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate vfstab = fopen(VFSTAB, "r"); 5647c478bd9Sstevel@tonic-gate if (vfstab == NULL) { 5657c478bd9Sstevel@tonic-gate (void) printf(gettext("can't open %s\n"), VFSTAB); 5667c478bd9Sstevel@tonic-gate return (1); 5677c478bd9Sstevel@tonic-gate } 5687c478bd9Sstevel@tonic-gate blkname = unrawname(name); 5697c478bd9Sstevel@tonic-gate if ((getvfsspec(vfstab, &vfsbuf, blkname) == 0) && 5707c478bd9Sstevel@tonic-gate (vfsbuf.vfs_fstype != NULL) && 5717c478bd9Sstevel@tonic-gate (strcmp(vfsbuf.vfs_fstype, MNTTYPE_UDFS) == 0) && 5727c478bd9Sstevel@tonic-gate (hasvfsopt(&vfsbuf, MNTOPT_RO))) { 5737c478bd9Sstevel@tonic-gate rw = 0; 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate (void) fclose(vfstab); 5767c478bd9Sstevel@tonic-gate return (rw); 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate /* 5807c478bd9Sstevel@tonic-gate * print out clean info 5817c478bd9Sstevel@tonic-gate */ 5827c478bd9Sstevel@tonic-gate void 5837c478bd9Sstevel@tonic-gate printclean() 5847c478bd9Sstevel@tonic-gate { 5857c478bd9Sstevel@tonic-gate char *s; 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate switch (lvintp->lvid_int_type) { 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate case LVI_CLOSE: 5907c478bd9Sstevel@tonic-gate s = gettext("clean"); 5917c478bd9Sstevel@tonic-gate break; 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate case LVI_OPEN: 5947c478bd9Sstevel@tonic-gate s = gettext("active"); 5957c478bd9Sstevel@tonic-gate break; 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate default: 5987c478bd9Sstevel@tonic-gate s = gettext("unknown"); 5997c478bd9Sstevel@tonic-gate } 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate if (preen) 6027c478bd9Sstevel@tonic-gate pwarn(gettext("is %s.\n"), s); 6037c478bd9Sstevel@tonic-gate else 6047c478bd9Sstevel@tonic-gate (void) printf("** %s is %s.\n", devname, s); 6057c478bd9Sstevel@tonic-gate } 606