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