17c478bd9Sstevel@tonic-gate /*
290eb94cfSns158690 * Copyright 2006 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) 1984, 1986, 1987, 1988, 1989 AT&T */
77c478bd9Sstevel@tonic-gate /* All Rights Reserved */
87c478bd9Sstevel@tonic-gate
97c478bd9Sstevel@tonic-gate /*
107c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California.
117c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement
127c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution.
137c478bd9Sstevel@tonic-gate */
147c478bd9Sstevel@tonic-gate
157c478bd9Sstevel@tonic-gate #include "dump.h"
167c478bd9Sstevel@tonic-gate #include <sys/file.h>
177c478bd9Sstevel@tonic-gate #include <sys/mman.h>
187c478bd9Sstevel@tonic-gate
197c478bd9Sstevel@tonic-gate static void lf_dmpindir(daddr32_t, int, u_offset_t *);
207c478bd9Sstevel@tonic-gate static void indir(daddr32_t, int, u_offset_t *);
217c478bd9Sstevel@tonic-gate static void lf_blksout(daddr32_t *, u_offset_t);
227c478bd9Sstevel@tonic-gate static void lf_dumpinode(struct dinode *);
237c478bd9Sstevel@tonic-gate static void dsrch(daddr32_t, ulong_t, u_offset_t);
247c478bd9Sstevel@tonic-gate void lf_dump(struct dinode *);
257c478bd9Sstevel@tonic-gate
26*e0dfa398SToomas Soome int dadded;
27*e0dfa398SToomas Soome int nsubdir;
28*e0dfa398SToomas Soome int shortmeta;
297c478bd9Sstevel@tonic-gate static char msgbuf[256];
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate void
pass(void (* fn)(struct dinode *),uchar_t * map)32*e0dfa398SToomas Soome pass(void (*fn)(struct dinode *), uchar_t *map)
337c478bd9Sstevel@tonic-gate {
347c478bd9Sstevel@tonic-gate int bits;
357c478bd9Sstevel@tonic-gate ino_t maxino;
367c478bd9Sstevel@tonic-gate
377c478bd9Sstevel@tonic-gate maxino = (unsigned)(sblock->fs_ipg * sblock->fs_ncg - 1);
387c478bd9Sstevel@tonic-gate /*
397c478bd9Sstevel@tonic-gate * Handle pass restarts. We don't check for UFSROOTINO just in
407c478bd9Sstevel@tonic-gate * case we need to restart on the root inode.
417c478bd9Sstevel@tonic-gate */
427c478bd9Sstevel@tonic-gate if (ino != 0) {
437c478bd9Sstevel@tonic-gate bits = ~0;
447c478bd9Sstevel@tonic-gate if (map != NULL) {
457c478bd9Sstevel@tonic-gate /* LINTED: lint seems to think map is signed */
467c478bd9Sstevel@tonic-gate map += (ino / NBBY);
477c478bd9Sstevel@tonic-gate bits = *map++;
487c478bd9Sstevel@tonic-gate }
497c478bd9Sstevel@tonic-gate bits >>= (ino % NBBY);
507c478bd9Sstevel@tonic-gate resetino(ino);
517c478bd9Sstevel@tonic-gate goto restart;
527c478bd9Sstevel@tonic-gate }
537c478bd9Sstevel@tonic-gate while (ino < maxino) {
547c478bd9Sstevel@tonic-gate if ((ino % NBBY) == 0) {
557c478bd9Sstevel@tonic-gate bits = ~0;
567c478bd9Sstevel@tonic-gate if (map != NULL)
577c478bd9Sstevel@tonic-gate bits = *map++;
587c478bd9Sstevel@tonic-gate }
597c478bd9Sstevel@tonic-gate restart:
607c478bd9Sstevel@tonic-gate ino++;
617c478bd9Sstevel@tonic-gate /*
627c478bd9Sstevel@tonic-gate * Ignore any inode less than UFSROOTINO and inodes that
637c478bd9Sstevel@tonic-gate * we have already done on a previous pass.
647c478bd9Sstevel@tonic-gate */
657c478bd9Sstevel@tonic-gate if ((ino >= UFSROOTINO) && (bits & 1)) {
667c478bd9Sstevel@tonic-gate /*
677c478bd9Sstevel@tonic-gate * The following test is merely an optimization
687c478bd9Sstevel@tonic-gate * for common case where "add" will just return.
697c478bd9Sstevel@tonic-gate */
707c478bd9Sstevel@tonic-gate if (!(fn == add && BIT(ino, nodmap)))
717c478bd9Sstevel@tonic-gate (*fn)(getino(ino));
727c478bd9Sstevel@tonic-gate }
737c478bd9Sstevel@tonic-gate bits >>= 1;
747c478bd9Sstevel@tonic-gate }
757c478bd9Sstevel@tonic-gate }
767c478bd9Sstevel@tonic-gate
777c478bd9Sstevel@tonic-gate void
mark(struct dinode * ip)78*e0dfa398SToomas Soome mark(struct dinode *ip)
797c478bd9Sstevel@tonic-gate {
807c478bd9Sstevel@tonic-gate int f;
817c478bd9Sstevel@tonic-gate
827c478bd9Sstevel@tonic-gate f = ip->di_mode & IFMT;
837c478bd9Sstevel@tonic-gate if (f == 0 || ip->di_nlink <= 0) {
847c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */
857c478bd9Sstevel@tonic-gate BIC(ino, clrmap);
867c478bd9Sstevel@tonic-gate return;
877c478bd9Sstevel@tonic-gate }
887c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */
897c478bd9Sstevel@tonic-gate BIS(ino, clrmap);
907c478bd9Sstevel@tonic-gate if (f == IFDIR || f == IFATTRDIR) {
917c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */
927c478bd9Sstevel@tonic-gate BIS(ino, dirmap);
937c478bd9Sstevel@tonic-gate }
947c478bd9Sstevel@tonic-gate if (ip->di_ctime >= spcl.c_ddate) {
957c478bd9Sstevel@tonic-gate if (f == IFSHAD)
967c478bd9Sstevel@tonic-gate return;
977c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */
987c478bd9Sstevel@tonic-gate BIS(ino, nodmap);
997c478bd9Sstevel@tonic-gate /* attribute changes impact the root */
1007c478bd9Sstevel@tonic-gate if (f == IFATTRDIR)
1017c478bd9Sstevel@tonic-gate BIS(UFSROOTINO, nodmap);
1027c478bd9Sstevel@tonic-gate if (f != IFREG && f != IFDIR && f != IFATTRDIR && f != IFLNK) {
1037c478bd9Sstevel@tonic-gate o_esize += 1;
1047c478bd9Sstevel@tonic-gate return;
1057c478bd9Sstevel@tonic-gate }
1067c478bd9Sstevel@tonic-gate est(ip);
1077c478bd9Sstevel@tonic-gate }
1087c478bd9Sstevel@tonic-gate }
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate void
active_mark(struct dinode * ip)111*e0dfa398SToomas Soome active_mark(struct dinode *ip)
1127c478bd9Sstevel@tonic-gate {
1137c478bd9Sstevel@tonic-gate int f;
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate f = ip->di_mode & IFMT;
1167c478bd9Sstevel@tonic-gate if (f == 0 || ip->di_nlink <= 0) {
1177c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */
1187c478bd9Sstevel@tonic-gate BIC(ino, clrmap);
1197c478bd9Sstevel@tonic-gate return;
1207c478bd9Sstevel@tonic-gate }
1217c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */
1227c478bd9Sstevel@tonic-gate BIS(ino, clrmap);
1237c478bd9Sstevel@tonic-gate if (f == IFDIR || f == IFATTRDIR) {
1247c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */
1257c478bd9Sstevel@tonic-gate BIS(ino, dirmap);
1267c478bd9Sstevel@tonic-gate }
1277c478bd9Sstevel@tonic-gate if (BIT(ino, activemap)) {
1287c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */
1297c478bd9Sstevel@tonic-gate BIS(ino, nodmap);
1307c478bd9Sstevel@tonic-gate /* attribute changes impact the root */
1317c478bd9Sstevel@tonic-gate if (f == IFATTRDIR)
1327c478bd9Sstevel@tonic-gate BIS(UFSROOTINO, nodmap);
1337c478bd9Sstevel@tonic-gate if (f != IFREG && f != IFDIR && f != IFATTRDIR && f != IFLNK) {
1347c478bd9Sstevel@tonic-gate o_esize += 1;
1357c478bd9Sstevel@tonic-gate return;
1367c478bd9Sstevel@tonic-gate }
1377c478bd9Sstevel@tonic-gate est(ip);
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate }
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate static struct shcount {
1427c478bd9Sstevel@tonic-gate struct shcount *higher, *lower;
1437c478bd9Sstevel@tonic-gate ino_t ino;
1447c478bd9Sstevel@tonic-gate unsigned long count;
1457c478bd9Sstevel@tonic-gate } shcounts = {
1467c478bd9Sstevel@tonic-gate NULL, NULL,
1477c478bd9Sstevel@tonic-gate 0,
1487c478bd9Sstevel@tonic-gate 0
1497c478bd9Sstevel@tonic-gate };
1507c478bd9Sstevel@tonic-gate static struct shcount *shc = NULL;
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate void
markshad(struct dinode * ip)153*e0dfa398SToomas Soome markshad(struct dinode *ip)
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate ino_t shadow;
1567c478bd9Sstevel@tonic-gate
1577c478bd9Sstevel@tonic-gate if (ip->di_shadow == 0)
1587c478bd9Sstevel@tonic-gate return;
1597c478bd9Sstevel@tonic-gate if (shc == NULL)
1607c478bd9Sstevel@tonic-gate shc = &shcounts;
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate shadow = (ino_t)(unsigned)(ip->di_shadow);
1637c478bd9Sstevel@tonic-gate while ((shadow > shc->ino) && (shc->higher))
1647c478bd9Sstevel@tonic-gate shc = shc->higher;
1657c478bd9Sstevel@tonic-gate while ((shadow < shc->ino) && (shc->lower))
1667c478bd9Sstevel@tonic-gate shc = shc->lower;
1677c478bd9Sstevel@tonic-gate if (shadow != shc->ino) {
1687c478bd9Sstevel@tonic-gate struct shcount *new;
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate new = (struct shcount *)xcalloc(1, sizeof (*new));
1717c478bd9Sstevel@tonic-gate new->higher = shc->higher;
1727c478bd9Sstevel@tonic-gate if (shc->higher != NULL)
1737c478bd9Sstevel@tonic-gate shc->higher->lower = new;
1747c478bd9Sstevel@tonic-gate shc->higher = new;
1757c478bd9Sstevel@tonic-gate new->lower = shc;
1767c478bd9Sstevel@tonic-gate shc = new;
1777c478bd9Sstevel@tonic-gate shc->ino = shadow;
1787c478bd9Sstevel@tonic-gate }
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */
1817c478bd9Sstevel@tonic-gate BIS(shadow, shamap);
1827c478bd9Sstevel@tonic-gate shc->count++;
1837c478bd9Sstevel@tonic-gate }
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate void
estshad(struct dinode * ip)186*e0dfa398SToomas Soome estshad(struct dinode *ip)
1877c478bd9Sstevel@tonic-gate {
1887c478bd9Sstevel@tonic-gate u_offset_t esizeprime;
1897c478bd9Sstevel@tonic-gate u_offset_t tmpesize;
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate if (ip->di_size <= sizeof (union u_shadow))
1927c478bd9Sstevel@tonic-gate return;
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate while ((ino > shc->ino) && (shc->higher))
1957c478bd9Sstevel@tonic-gate shc = shc->higher;
1967c478bd9Sstevel@tonic-gate while ((ino < shc->ino) && (shc->lower))
1977c478bd9Sstevel@tonic-gate shc = shc->lower;
1987c478bd9Sstevel@tonic-gate if (ino != shc->ino)
1997c478bd9Sstevel@tonic-gate return; /* xxx panic? complain? */
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate tmpesize = (o_esize + f_esize);
2027c478bd9Sstevel@tonic-gate esizeprime = tmpesize;
2037c478bd9Sstevel@tonic-gate est(ip);
2047c478bd9Sstevel@tonic-gate esizeprime = tmpesize - esizeprime;
2057c478bd9Sstevel@tonic-gate esizeprime *= shc->count - 1;
2067c478bd9Sstevel@tonic-gate f_esize += esizeprime;
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate void
freeshad()2107c478bd9Sstevel@tonic-gate freeshad()
2117c478bd9Sstevel@tonic-gate {
2127c478bd9Sstevel@tonic-gate if (shc == NULL)
2137c478bd9Sstevel@tonic-gate return;
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate while (shc->higher)
2167c478bd9Sstevel@tonic-gate shc = shc->higher;
2177c478bd9Sstevel@tonic-gate while (shc->lower) {
2187c478bd9Sstevel@tonic-gate shc = shc->lower;
2197c478bd9Sstevel@tonic-gate if (shc->higher) /* else panic? */
2207c478bd9Sstevel@tonic-gate (void) free(shc->higher);
2217c478bd9Sstevel@tonic-gate }
2227c478bd9Sstevel@tonic-gate /*
2237c478bd9Sstevel@tonic-gate * This should be unnecessary, but do it just to be safe.
2247c478bd9Sstevel@tonic-gate * Note that shc might be malloc'd or static, so can't free().
2257c478bd9Sstevel@tonic-gate */
2267c478bd9Sstevel@tonic-gate bzero(shc, sizeof (*shc));
2277c478bd9Sstevel@tonic-gate }
2287c478bd9Sstevel@tonic-gate
2297c478bd9Sstevel@tonic-gate void
add(struct dinode * ip)230*e0dfa398SToomas Soome add(struct dinode *ip)
2317c478bd9Sstevel@tonic-gate {
2327c478bd9Sstevel@tonic-gate int i;
2337c478bd9Sstevel@tonic-gate u_offset_t filesize;
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate if (BIT(ino, nodmap))
2367c478bd9Sstevel@tonic-gate return;
2377c478bd9Sstevel@tonic-gate if ((ip->di_mode & IFMT) != IFDIR &&
2387c478bd9Sstevel@tonic-gate (ip->di_mode & IFMT) != IFATTRDIR) {
2397c478bd9Sstevel@tonic-gate (void) snprintf(msgbuf, sizeof (msgbuf), gettext(
2407c478bd9Sstevel@tonic-gate "Warning - directory at inode `%lu' vanished!\n"), ino);
2417c478bd9Sstevel@tonic-gate msg(msgbuf);
2427c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */
2437c478bd9Sstevel@tonic-gate BIC(ino, dirmap);
2447c478bd9Sstevel@tonic-gate return;
2457c478bd9Sstevel@tonic-gate }
2467c478bd9Sstevel@tonic-gate nsubdir = 0;
2477c478bd9Sstevel@tonic-gate dadded = 0;
2487c478bd9Sstevel@tonic-gate filesize = ip->di_size;
2497c478bd9Sstevel@tonic-gate for (i = 0; i < NDADDR; i++) {
2507c478bd9Sstevel@tonic-gate if (ip->di_db[i] != 0)
2517c478bd9Sstevel@tonic-gate /* LINTED dblksize/blkoff does a safe cast here */
2527c478bd9Sstevel@tonic-gate dsrch(ip->di_db[i], (ulong_t)dblksize(sblock, ip, i),
2537c478bd9Sstevel@tonic-gate filesize);
2547c478bd9Sstevel@tonic-gate filesize -= (unsigned)(sblock->fs_bsize);
2557c478bd9Sstevel@tonic-gate }
2567c478bd9Sstevel@tonic-gate for (i = 0; i < NIADDR; i++) {
2577c478bd9Sstevel@tonic-gate if (ip->di_ib[i] != 0)
2587c478bd9Sstevel@tonic-gate indir(ip->di_ib[i], i, &filesize);
2597c478bd9Sstevel@tonic-gate }
2607c478bd9Sstevel@tonic-gate if (dadded) {
2617c478bd9Sstevel@tonic-gate nadded++;
2627c478bd9Sstevel@tonic-gate if (!BIT(ino, nodmap)) {
2637c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */
2647c478bd9Sstevel@tonic-gate BIS(ino, nodmap);
2657c478bd9Sstevel@tonic-gate if ((ip->di_mode & IFMT) == IFATTRDIR) {
2667c478bd9Sstevel@tonic-gate /* attribute changes "auto-percolate" to root */
2677c478bd9Sstevel@tonic-gate BIS(UFSROOTINO, nodmap);
2687c478bd9Sstevel@tonic-gate }
2697c478bd9Sstevel@tonic-gate est(ip);
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate }
2727c478bd9Sstevel@tonic-gate if (nsubdir == 0) {
2737c478bd9Sstevel@tonic-gate if (!BIT(ino, nodmap)) {
2747c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */
2757c478bd9Sstevel@tonic-gate BIC(ino, dirmap);
2767c478bd9Sstevel@tonic-gate }
2777c478bd9Sstevel@tonic-gate }
2787c478bd9Sstevel@tonic-gate }
2797c478bd9Sstevel@tonic-gate
2807c478bd9Sstevel@tonic-gate static void
indir(daddr32_t d,int n,u_offset_t * filesize)281*e0dfa398SToomas Soome indir(daddr32_t d, int n, u_offset_t *filesize)
2827c478bd9Sstevel@tonic-gate {
2837c478bd9Sstevel@tonic-gate int i;
2847c478bd9Sstevel@tonic-gate daddr32_t idblk[MAXNINDIR];
2857c478bd9Sstevel@tonic-gate
2867c478bd9Sstevel@tonic-gate if ((unsigned)(sblock->fs_bsize) > sizeof (idblk)) {
2877c478bd9Sstevel@tonic-gate msg(gettext(
2887c478bd9Sstevel@tonic-gate "Inconsistency detected: filesystem block size larger than valid maximum.\n"));
2897c478bd9Sstevel@tonic-gate dumpabort();
2907c478bd9Sstevel@tonic-gate /*NOTREACHED*/
2917c478bd9Sstevel@tonic-gate }
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate if ((unsigned)NINDIR(sblock) > MAXNINDIR) {
2947c478bd9Sstevel@tonic-gate /*CSTYLED*/
2957c478bd9Sstevel@tonic-gate msg(gettext(
2967c478bd9Sstevel@tonic-gate "Inconsistency detected: inode has more indirect \
2977c478bd9Sstevel@tonic-gate blocks than valid maximum.\n"));
2987c478bd9Sstevel@tonic-gate dumpabort();
2997c478bd9Sstevel@tonic-gate /*NOTREACHED*/
3007c478bd9Sstevel@tonic-gate }
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate if (dadded || *filesize == 0)
3037c478bd9Sstevel@tonic-gate return;
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate #ifdef lint
3067c478bd9Sstevel@tonic-gate idblk[0] = '\0';
3077c478bd9Sstevel@tonic-gate #endif /* lint */
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate /* xxx sanity check sblock contents before trusting them */
3107c478bd9Sstevel@tonic-gate bread(fsbtodb(sblock, d), (uchar_t *)idblk, (size_t)sblock->fs_bsize);
3117c478bd9Sstevel@tonic-gate if (n <= 0) {
3127c478bd9Sstevel@tonic-gate for (i = 0; i < NINDIR(sblock); i++) {
3137c478bd9Sstevel@tonic-gate d = idblk[i];
3147c478bd9Sstevel@tonic-gate if (d != 0)
3157c478bd9Sstevel@tonic-gate dsrch(d, (ulong_t)(uint32_t)sblock->fs_bsize,
3167c478bd9Sstevel@tonic-gate *filesize);
3177c478bd9Sstevel@tonic-gate *filesize -= (unsigned)(sblock->fs_bsize);
3187c478bd9Sstevel@tonic-gate }
3197c478bd9Sstevel@tonic-gate } else {
3207c478bd9Sstevel@tonic-gate n--;
3217c478bd9Sstevel@tonic-gate for (i = 0; i < NINDIR(sblock); i++) {
3227c478bd9Sstevel@tonic-gate d = idblk[i];
3237c478bd9Sstevel@tonic-gate if (d != 0)
3247c478bd9Sstevel@tonic-gate indir(d, n, filesize);
3257c478bd9Sstevel@tonic-gate }
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate }
3287c478bd9Sstevel@tonic-gate
3297c478bd9Sstevel@tonic-gate void
dirdump(struct dinode * ip)330*e0dfa398SToomas Soome dirdump(struct dinode *ip)
3317c478bd9Sstevel@tonic-gate {
3327c478bd9Sstevel@tonic-gate /* watchout for dir inodes deleted and maybe reallocated */
3337c478bd9Sstevel@tonic-gate if (((ip->di_mode & IFMT) != IFDIR &&
3347c478bd9Sstevel@tonic-gate (ip->di_mode & IFMT) != IFATTRDIR) || ip->di_nlink < 2) {
3357c478bd9Sstevel@tonic-gate (void) snprintf(msgbuf, sizeof (msgbuf), gettext(
336*e0dfa398SToomas Soome "Warning - directory at inode `%lu' vanished!\n"), ino);
3377c478bd9Sstevel@tonic-gate msg(msgbuf);
3387c478bd9Sstevel@tonic-gate return;
3397c478bd9Sstevel@tonic-gate }
3407c478bd9Sstevel@tonic-gate lf_dump(ip);
3417c478bd9Sstevel@tonic-gate }
3427c478bd9Sstevel@tonic-gate
3437c478bd9Sstevel@tonic-gate static u_offset_t loffset; /* current offset in file (ufsdump) */
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate static void
lf_dumpmeta(struct dinode * ip)346*e0dfa398SToomas Soome lf_dumpmeta(struct dinode *ip)
3477c478bd9Sstevel@tonic-gate {
3487c478bd9Sstevel@tonic-gate if ((ip->di_shadow == 0) || shortmeta)
3497c478bd9Sstevel@tonic-gate return;
3507c478bd9Sstevel@tonic-gate
3517c478bd9Sstevel@tonic-gate lf_dumpinode(getino((ino_t)(unsigned)(ip->di_shadow)));
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate
3547c478bd9Sstevel@tonic-gate int
hasshortmeta(struct dinode ** ip)355*e0dfa398SToomas Soome hasshortmeta(struct dinode **ip)
3567c478bd9Sstevel@tonic-gate {
3577c478bd9Sstevel@tonic-gate ino_t savino;
3587c478bd9Sstevel@tonic-gate int rc;
3597c478bd9Sstevel@tonic-gate
3607c478bd9Sstevel@tonic-gate if ((*ip)->di_shadow == 0)
3617c478bd9Sstevel@tonic-gate return (0);
3627c478bd9Sstevel@tonic-gate savino = ino;
3637c478bd9Sstevel@tonic-gate *ip = getino((ino_t)(unsigned)((*ip)->di_shadow));
3647c478bd9Sstevel@tonic-gate rc = ((*ip)->di_size <= sizeof (union u_shadow));
3657c478bd9Sstevel@tonic-gate *ip = getino(ino = savino);
3667c478bd9Sstevel@tonic-gate return (rc);
3677c478bd9Sstevel@tonic-gate }
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate void
lf_dumpinode(struct dinode * ip)370*e0dfa398SToomas Soome lf_dumpinode(struct dinode *ip)
3717c478bd9Sstevel@tonic-gate {
3727c478bd9Sstevel@tonic-gate int i;
3737c478bd9Sstevel@tonic-gate u_offset_t size;
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate i = ip->di_mode & IFMT;
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gate if (i == 0 || ip->di_nlink <= 0)
3787c478bd9Sstevel@tonic-gate return;
3797c478bd9Sstevel@tonic-gate
3807c478bd9Sstevel@tonic-gate spcl.c_dinode = *ip;
3817c478bd9Sstevel@tonic-gate spcl.c_count = 0;
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate if ((i != IFDIR && i != IFATTRDIR && i != IFREG && i != IFLNK &&
3847c478bd9Sstevel@tonic-gate i != IFSHAD) || ip->di_size == 0) {
3857c478bd9Sstevel@tonic-gate toslave(dospcl, ino);
3867c478bd9Sstevel@tonic-gate return;
3877c478bd9Sstevel@tonic-gate }
3887c478bd9Sstevel@tonic-gate
3897c478bd9Sstevel@tonic-gate size = NDADDR * (unsigned)(sblock->fs_bsize);
3907c478bd9Sstevel@tonic-gate if (size > ip->di_size)
3917c478bd9Sstevel@tonic-gate size = ip->di_size;
3927c478bd9Sstevel@tonic-gate
3937c478bd9Sstevel@tonic-gate lf_blksout(&ip->di_db[0], size);
3947c478bd9Sstevel@tonic-gate
3957c478bd9Sstevel@tonic-gate size = ip->di_size - size;
3967c478bd9Sstevel@tonic-gate if (size > 0) {
3977c478bd9Sstevel@tonic-gate for (i = 0; i < NIADDR; i++) {
3987c478bd9Sstevel@tonic-gate lf_dmpindir(ip->di_ib[i], i, &size);
3997c478bd9Sstevel@tonic-gate if (size == 0)
4007c478bd9Sstevel@tonic-gate break;
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate }
4037c478bd9Sstevel@tonic-gate }
4047c478bd9Sstevel@tonic-gate
4057c478bd9Sstevel@tonic-gate void
lf_dump(struct dinode * ip)406*e0dfa398SToomas Soome lf_dump(struct dinode *ip)
4077c478bd9Sstevel@tonic-gate {
4087c478bd9Sstevel@tonic-gate
4097c478bd9Sstevel@tonic-gate if ((!BIT(ino, nodmap)) && (!BIT(ino, shamap)))
4107c478bd9Sstevel@tonic-gate return;
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate shortmeta = hasshortmeta(&ip);
4137c478bd9Sstevel@tonic-gate if (shortmeta) {
4147c478bd9Sstevel@tonic-gate ip = getino((ino_t)(unsigned)(ip->di_shadow));
4157c478bd9Sstevel@tonic-gate /* assume spcl.c_shadow is smaller than 1 block */
4167c478bd9Sstevel@tonic-gate bread(fsbtodb(sblock, ip->di_db[0]),
4177c478bd9Sstevel@tonic-gate (uchar_t *)spcl.c_shadow.c_shadow, sizeof (spcl.c_shadow));
4187c478bd9Sstevel@tonic-gate spcl.c_flags |= DR_HASMETA;
4197c478bd9Sstevel@tonic-gate } else {
4207c478bd9Sstevel@tonic-gate spcl.c_flags &= ~DR_HASMETA;
4217c478bd9Sstevel@tonic-gate }
4227c478bd9Sstevel@tonic-gate ip = getino(ino);
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate loffset = 0;
4257c478bd9Sstevel@tonic-gate
4267c478bd9Sstevel@tonic-gate if (newtape) {
4277c478bd9Sstevel@tonic-gate spcl.c_type = TS_TAPE;
4287c478bd9Sstevel@tonic-gate } else if (pos)
4297c478bd9Sstevel@tonic-gate spcl.c_type = TS_ADDR;
4307c478bd9Sstevel@tonic-gate else
4317c478bd9Sstevel@tonic-gate spcl.c_type = TS_INODE;
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate newtape = 0;
4347c478bd9Sstevel@tonic-gate lf_dumpinode(ip);
4357c478bd9Sstevel@tonic-gate lf_dumpmeta(ip);
4367c478bd9Sstevel@tonic-gate pos = 0;
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate static void
lf_dmpindir(daddr32_t blk,int lvl,u_offset_t * size)440*e0dfa398SToomas Soome lf_dmpindir(daddr32_t blk, int lvl, u_offset_t *size)
4417c478bd9Sstevel@tonic-gate {
4427c478bd9Sstevel@tonic-gate int i;
4437c478bd9Sstevel@tonic-gate u_offset_t cnt;
4447c478bd9Sstevel@tonic-gate daddr32_t idblk[MAXNINDIR];
4457c478bd9Sstevel@tonic-gate
4467c478bd9Sstevel@tonic-gate if ((unsigned)(sblock->fs_bsize) > sizeof (idblk)) {
4477c478bd9Sstevel@tonic-gate msg(gettext(
4487c478bd9Sstevel@tonic-gate "Inconsistency detected: filesystem block size larger than valid maximum.\n"));
4497c478bd9Sstevel@tonic-gate dumpabort();
4507c478bd9Sstevel@tonic-gate /*NOTREACHED*/
4517c478bd9Sstevel@tonic-gate }
4527c478bd9Sstevel@tonic-gate
4537c478bd9Sstevel@tonic-gate if ((unsigned)NINDIR(sblock) > MAXNINDIR) {
4547c478bd9Sstevel@tonic-gate msg(gettext(
4557c478bd9Sstevel@tonic-gate "Inconsistency detected: inode has more indirect \
4567c478bd9Sstevel@tonic-gate blocks than valid maximum.\n"));
4577c478bd9Sstevel@tonic-gate dumpabort();
4587c478bd9Sstevel@tonic-gate /*NOTREACHED*/
4597c478bd9Sstevel@tonic-gate }
4607c478bd9Sstevel@tonic-gate
4617c478bd9Sstevel@tonic-gate if (blk != 0)
4627c478bd9Sstevel@tonic-gate bread(fsbtodb(sblock, blk), (uchar_t *)idblk,
4637c478bd9Sstevel@tonic-gate (size_t)sblock->fs_bsize);
4647c478bd9Sstevel@tonic-gate else
4657c478bd9Sstevel@tonic-gate bzero((char *)idblk, (size_t)sblock->fs_bsize);
4667c478bd9Sstevel@tonic-gate if (lvl <= 0) {
4677c478bd9Sstevel@tonic-gate cnt = (u_offset_t)(unsigned)NINDIR(sblock) *
4687c478bd9Sstevel@tonic-gate (u_offset_t)(unsigned)(sblock->fs_bsize);
4697c478bd9Sstevel@tonic-gate if (cnt > *size)
4707c478bd9Sstevel@tonic-gate cnt = *size;
4717c478bd9Sstevel@tonic-gate *size -= cnt;
4727c478bd9Sstevel@tonic-gate lf_blksout(&idblk[0], cnt);
4737c478bd9Sstevel@tonic-gate return;
4747c478bd9Sstevel@tonic-gate }
4757c478bd9Sstevel@tonic-gate lvl--;
4767c478bd9Sstevel@tonic-gate for (i = 0; i < NINDIR(sblock); i++) {
4777c478bd9Sstevel@tonic-gate lf_dmpindir(idblk[i], lvl, size);
4787c478bd9Sstevel@tonic-gate if (*size == 0)
4797c478bd9Sstevel@tonic-gate return;
4807c478bd9Sstevel@tonic-gate }
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate
4837c478bd9Sstevel@tonic-gate static void
lf_blksout(daddr32_t * blkp,u_offset_t bytes)484*e0dfa398SToomas Soome lf_blksout(daddr32_t *blkp, u_offset_t bytes)
4857c478bd9Sstevel@tonic-gate {
4867c478bd9Sstevel@tonic-gate u_offset_t i;
4877c478bd9Sstevel@tonic-gate u_offset_t tbperfsb = (unsigned)(sblock->fs_bsize / tp_bsize);
4887c478bd9Sstevel@tonic-gate
4897c478bd9Sstevel@tonic-gate u_offset_t j, k, count;
4907c478bd9Sstevel@tonic-gate
4917c478bd9Sstevel@tonic-gate u_offset_t bytepos, diff;
4927c478bd9Sstevel@tonic-gate u_offset_t bytecnt = 0;
4937c478bd9Sstevel@tonic-gate off_t byteoff = 0; /* bytes to skip within first f/s block */
4947c478bd9Sstevel@tonic-gate off_t fragoff = 0; /* frags to skip within first f/s block */
4957c478bd9Sstevel@tonic-gate
4967c478bd9Sstevel@tonic-gate u_offset_t tpblkoff = 0; /* tape blocks to skip in first f/s block */
4977c478bd9Sstevel@tonic-gate u_offset_t tpblkskip = 0; /* total tape blocks to skip */
4987c478bd9Sstevel@tonic-gate u_offset_t skip; /* tape blocks to skip this pass */
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate if (pos) {
5017c478bd9Sstevel@tonic-gate /*
5027c478bd9Sstevel@tonic-gate * We get here if a slave throws a signal to the
5037c478bd9Sstevel@tonic-gate * master indicating a partially dumped file.
5047c478bd9Sstevel@tonic-gate * Begin by figuring out what was undone.
5057c478bd9Sstevel@tonic-gate */
5067c478bd9Sstevel@tonic-gate bytepos = (offset_t)pos * tp_bsize;
5077c478bd9Sstevel@tonic-gate
5087c478bd9Sstevel@tonic-gate if ((loffset + bytes) <= bytepos) {
5097c478bd9Sstevel@tonic-gate /* This stuff was dumped already, forget it. */
5107c478bd9Sstevel@tonic-gate loffset += (u_offset_t)tp_bsize *
5117c478bd9Sstevel@tonic-gate /* LINTED: spurious complaint on sign-extending */
5127c478bd9Sstevel@tonic-gate d_howmany(bytes, (u_offset_t)tp_bsize);
5137c478bd9Sstevel@tonic-gate return;
5147c478bd9Sstevel@tonic-gate }
5157c478bd9Sstevel@tonic-gate
5167c478bd9Sstevel@tonic-gate if (loffset < bytepos) {
5177c478bd9Sstevel@tonic-gate /*
5187c478bd9Sstevel@tonic-gate * Some of this was dumped, some wasn't.
5197c478bd9Sstevel@tonic-gate * Figure out what was done and skip it.
5207c478bd9Sstevel@tonic-gate */
5217c478bd9Sstevel@tonic-gate diff = bytepos - loffset;
5227c478bd9Sstevel@tonic-gate /* LINTED: spurious complaint on sign-extending */
5237c478bd9Sstevel@tonic-gate tpblkskip = d_howmany(diff, (u_offset_t)tp_bsize);
5247c478bd9Sstevel@tonic-gate /* LINTED room after EOT is only a few MB */
5257c478bd9Sstevel@tonic-gate blkp += (int)(diff / sblock->fs_bsize);
5267c478bd9Sstevel@tonic-gate
5277c478bd9Sstevel@tonic-gate bytecnt = diff % (unsigned)(sblock->fs_bsize);
5287c478bd9Sstevel@tonic-gate /* LINTED: result fits, due to modulus */
5297c478bd9Sstevel@tonic-gate byteoff = bytecnt % (off_t)(sblock->fs_fsize);
5307c478bd9Sstevel@tonic-gate /* LINTED: spurious complaint on sign-extending */
5317c478bd9Sstevel@tonic-gate tpblkoff = d_howmany(bytecnt,
5327c478bd9Sstevel@tonic-gate (u_offset_t)(unsigned)tp_bsize);
5337c478bd9Sstevel@tonic-gate /* LINTED: result fits, due to modulus */
5347c478bd9Sstevel@tonic-gate fragoff = bytecnt / (off_t)(sblock->fs_fsize);
5357c478bd9Sstevel@tonic-gate bytecnt = (unsigned)(sblock->fs_bsize) - bytecnt;
5367c478bd9Sstevel@tonic-gate }
5377c478bd9Sstevel@tonic-gate }
5387c478bd9Sstevel@tonic-gate
5397c478bd9Sstevel@tonic-gate loffset += bytes;
5407c478bd9Sstevel@tonic-gate
5417c478bd9Sstevel@tonic-gate while (bytes > 0) {
5427c478bd9Sstevel@tonic-gate if (bytes < TP_NINDIR*tp_bsize)
5437c478bd9Sstevel@tonic-gate /* LINTED: spurious complaint on sign-extending */
5447c478bd9Sstevel@tonic-gate count = d_howmany(bytes, (u_offset_t)tp_bsize);
5457c478bd9Sstevel@tonic-gate else
5467c478bd9Sstevel@tonic-gate count = TP_NINDIR;
5477c478bd9Sstevel@tonic-gate if (tpblkskip) {
5487c478bd9Sstevel@tonic-gate if (tpblkskip < TP_NINDIR) {
5497c478bd9Sstevel@tonic-gate bytes -= (tpblkskip * (u_offset_t)tp_bsize);
5507c478bd9Sstevel@tonic-gate skip = tpblkskip;
5517c478bd9Sstevel@tonic-gate tpblkskip = 0;
5527c478bd9Sstevel@tonic-gate } else {
5537c478bd9Sstevel@tonic-gate bytes -= (offset_t)TP_NINDIR*tp_bsize;
5547c478bd9Sstevel@tonic-gate tpblkskip -= TP_NINDIR;
5557c478bd9Sstevel@tonic-gate continue;
5567c478bd9Sstevel@tonic-gate }
5577c478bd9Sstevel@tonic-gate } else
5587c478bd9Sstevel@tonic-gate skip = 0;
5597c478bd9Sstevel@tonic-gate assert(tbperfsb >= tpblkoff);
5607c478bd9Sstevel@tonic-gate assert((count - skip) <= TP_NINDIR);
5617c478bd9Sstevel@tonic-gate for (j = 0, k = 0; j < count - skip; j++, k++) {
5627c478bd9Sstevel@tonic-gate spcl.c_addr[j] = (blkp[k] != 0);
5637c478bd9Sstevel@tonic-gate for (i = tbperfsb - tpblkoff; --i > 0; j++)
5647c478bd9Sstevel@tonic-gate spcl.c_addr[j+1] = spcl.c_addr[j];
5657c478bd9Sstevel@tonic-gate tpblkoff = 0;
5667c478bd9Sstevel@tonic-gate }
5677c478bd9Sstevel@tonic-gate /* LINTED (count - skip) will always fit into an int32_t */
5687c478bd9Sstevel@tonic-gate spcl.c_count = count - skip;
5697c478bd9Sstevel@tonic-gate toslave(dospcl, ino);
5707c478bd9Sstevel@tonic-gate bytecnt = MIN(bytes, bytecnt ?
5717c478bd9Sstevel@tonic-gate bytecnt : (unsigned)(sblock->fs_bsize));
5727c478bd9Sstevel@tonic-gate j = 0;
5737c478bd9Sstevel@tonic-gate while (j < count - skip) {
5747c478bd9Sstevel@tonic-gate if (*blkp != 0) {
5757c478bd9Sstevel@tonic-gate /* LINTED: fragoff fits into 32 bits */
5767c478bd9Sstevel@tonic-gate dmpblk(*blkp+(int32_t)fragoff,
5777c478bd9Sstevel@tonic-gate /* LINTED: bytecnt fits into 32 bits */
5787c478bd9Sstevel@tonic-gate (size_t)bytecnt, byteoff);
5797c478bd9Sstevel@tonic-gate }
5807c478bd9Sstevel@tonic-gate blkp++;
5817c478bd9Sstevel@tonic-gate bytes -= bytecnt;
5827c478bd9Sstevel@tonic-gate /* LINTED: spurious complaint on sign-extending */
5837c478bd9Sstevel@tonic-gate j += d_howmany(bytecnt, (u_offset_t)tp_bsize);
5847c478bd9Sstevel@tonic-gate bytecnt = MIN(bytes, (unsigned)(sblock->fs_bsize));
5857c478bd9Sstevel@tonic-gate byteoff = 0;
5867c478bd9Sstevel@tonic-gate fragoff = 0;
5877c478bd9Sstevel@tonic-gate }
5887c478bd9Sstevel@tonic-gate spcl.c_type = TS_ADDR;
5897c478bd9Sstevel@tonic-gate bytecnt = 0;
5907c478bd9Sstevel@tonic-gate }
5917c478bd9Sstevel@tonic-gate pos = 0;
5927c478bd9Sstevel@tonic-gate }
5937c478bd9Sstevel@tonic-gate
5947c478bd9Sstevel@tonic-gate void
bitmap(uchar_t * map,int typ)595*e0dfa398SToomas Soome bitmap(uchar_t *map, int typ)
5967c478bd9Sstevel@tonic-gate {
5977c478bd9Sstevel@tonic-gate int i;
5987c478bd9Sstevel@tonic-gate u_offset_t count;
5997c478bd9Sstevel@tonic-gate uchar_t *cp;
6007c478bd9Sstevel@tonic-gate
6017c478bd9Sstevel@tonic-gate if (!newtape)
6027c478bd9Sstevel@tonic-gate spcl.c_type = typ;
6037c478bd9Sstevel@tonic-gate else
6047c478bd9Sstevel@tonic-gate newtape = 0;
6057c478bd9Sstevel@tonic-gate for (i = 0; i < TP_NINDIR; i++)
6067c478bd9Sstevel@tonic-gate spcl.c_addr[i] = 1;
6077c478bd9Sstevel@tonic-gate /* LINTED: spurious complaint on sign-extending */
6087c478bd9Sstevel@tonic-gate count = d_howmany(msiz * sizeof (map[0]), tp_bsize) - pos;
6097c478bd9Sstevel@tonic-gate for (cp = &map[pos * tp_bsize]; count > 0;
6107c478bd9Sstevel@tonic-gate count -= (u_offset_t)(unsigned)spcl.c_count) {
6117c478bd9Sstevel@tonic-gate if (leftover) {
6127c478bd9Sstevel@tonic-gate spcl.c_count = leftover;
6137c478bd9Sstevel@tonic-gate leftover = 0;
6147c478bd9Sstevel@tonic-gate } else {
6157c478bd9Sstevel@tonic-gate /* LINTED value always less than INT32_MAX */
6167c478bd9Sstevel@tonic-gate spcl.c_count = count > TP_NINDIR ? TP_NINDIR : count;
6177c478bd9Sstevel@tonic-gate }
6187c478bd9Sstevel@tonic-gate spclrec();
6197c478bd9Sstevel@tonic-gate for (i = 0; i < spcl.c_count; i++, cp += tp_bsize)
6207c478bd9Sstevel@tonic-gate taprec(cp, 0, tp_bsize);
6217c478bd9Sstevel@tonic-gate spcl.c_type = TS_ADDR;
6227c478bd9Sstevel@tonic-gate }
6237c478bd9Sstevel@tonic-gate }
6247c478bd9Sstevel@tonic-gate
6257c478bd9Sstevel@tonic-gate static void
dsrch(daddr32_t d,ulong_t size,u_offset_t filesize)626*e0dfa398SToomas Soome dsrch(daddr32_t d, ulong_t size, u_offset_t filesize)
6277c478bd9Sstevel@tonic-gate {
6287c478bd9Sstevel@tonic-gate struct direct *dp;
6297c478bd9Sstevel@tonic-gate struct dinode *ip;
6307c478bd9Sstevel@tonic-gate ulong_t loc;
6317c478bd9Sstevel@tonic-gate char dblk[MAXBSIZE];
6327c478bd9Sstevel@tonic-gate
6337c478bd9Sstevel@tonic-gate if (dadded || filesize == 0)
6347c478bd9Sstevel@tonic-gate return;
6357c478bd9Sstevel@tonic-gate if (filesize > (u_offset_t)size)
6367c478bd9Sstevel@tonic-gate filesize = (u_offset_t)size;
6377c478bd9Sstevel@tonic-gate if (sizeof (dblk) < roundup(filesize, DEV_BSIZE)) {
6387c478bd9Sstevel@tonic-gate msg(gettext(
6397c478bd9Sstevel@tonic-gate "Inconsistency detected: filesystem block size larger than valid maximum.\n"));
6407c478bd9Sstevel@tonic-gate dumpabort();
6417c478bd9Sstevel@tonic-gate /*NOTREACHED*/
6427c478bd9Sstevel@tonic-gate }
6437c478bd9Sstevel@tonic-gate
6447c478bd9Sstevel@tonic-gate #ifdef lint
6457c478bd9Sstevel@tonic-gate dblk[0] = '\0';
6467c478bd9Sstevel@tonic-gate #endif /* lint */
6477c478bd9Sstevel@tonic-gate
6487c478bd9Sstevel@tonic-gate /* LINTED ufs disk addresses always fit into 32 bits */
6497c478bd9Sstevel@tonic-gate bread(fsbtodb(sblock, d), (uchar_t *)dblk,
6507c478bd9Sstevel@tonic-gate /* LINTED from sizeof check above, roundup() <= max(size_t) */
6517c478bd9Sstevel@tonic-gate (size_t)(roundup(filesize, DEV_BSIZE)));
6527c478bd9Sstevel@tonic-gate loc = 0;
6537c478bd9Sstevel@tonic-gate while ((u_offset_t)loc < filesize) {
6547c478bd9Sstevel@tonic-gate /*LINTED [dblk is char[], loc (dp->d_reclen) % 4 == 0]*/
6557c478bd9Sstevel@tonic-gate dp = (struct direct *)(dblk + loc);
6567c478bd9Sstevel@tonic-gate if (dp->d_reclen == 0) {
6577c478bd9Sstevel@tonic-gate (void) snprintf(msgbuf, sizeof (msgbuf), gettext(
658*e0dfa398SToomas Soome "Warning - directory at inode `%lu' is "
659*e0dfa398SToomas Soome "corrupted\n"), ino);
6607c478bd9Sstevel@tonic-gate msg(msgbuf);
6617c478bd9Sstevel@tonic-gate break;
6627c478bd9Sstevel@tonic-gate }
6637c478bd9Sstevel@tonic-gate loc += dp->d_reclen;
6647c478bd9Sstevel@tonic-gate if (dp->d_ino == 0)
6657c478bd9Sstevel@tonic-gate continue;
6667c478bd9Sstevel@tonic-gate if (dp->d_name[0] == '.') {
6677c478bd9Sstevel@tonic-gate if (dp->d_name[1] == '\0') {
6687c478bd9Sstevel@tonic-gate if ((ino_t)(dp->d_ino) != ino) {
6697c478bd9Sstevel@tonic-gate (void) snprintf(msgbuf, sizeof (msgbuf),
6707c478bd9Sstevel@tonic-gate gettext(
6717c478bd9Sstevel@tonic-gate "Warning - directory at inode `%lu' is corrupted:\n\
6727c478bd9Sstevel@tonic-gate \t\".\" points to inode `%lu' - run fsck\n"),
6737c478bd9Sstevel@tonic-gate ino, dp->d_ino);
6747c478bd9Sstevel@tonic-gate msg(msgbuf);
6757c478bd9Sstevel@tonic-gate }
6767c478bd9Sstevel@tonic-gate continue;
6777c478bd9Sstevel@tonic-gate }
6787c478bd9Sstevel@tonic-gate if (dp->d_name[1] == '.' && dp->d_name[2] == '\0') {
6797c478bd9Sstevel@tonic-gate if (!BIT(dp->d_ino, dirmap) &&
6807c478bd9Sstevel@tonic-gate ((ip = getino(ino)) == NULL ||
6817c478bd9Sstevel@tonic-gate (ip->di_mode & IFMT) != IFATTRDIR)) {
6827c478bd9Sstevel@tonic-gate (void) snprintf(msgbuf, sizeof (msgbuf),
6837c478bd9Sstevel@tonic-gate gettext(
6847c478bd9Sstevel@tonic-gate "Warning - directory at inode `%lu' is corrupted:\n\
6857c478bd9Sstevel@tonic-gate \t\"..\" points to non-directory inode `%lu' - run fsck\n"),
6867c478bd9Sstevel@tonic-gate ino, dp->d_ino);
6877c478bd9Sstevel@tonic-gate msg(msgbuf);
6887c478bd9Sstevel@tonic-gate }
6897c478bd9Sstevel@tonic-gate continue;
6907c478bd9Sstevel@tonic-gate }
6917c478bd9Sstevel@tonic-gate }
6927c478bd9Sstevel@tonic-gate if (BIT(dp->d_ino, nodmap)) {
6937c478bd9Sstevel@tonic-gate dadded++;
6947c478bd9Sstevel@tonic-gate return;
6957c478bd9Sstevel@tonic-gate }
6967c478bd9Sstevel@tonic-gate if (BIT(dp->d_ino, dirmap))
6977c478bd9Sstevel@tonic-gate nsubdir++;
6987c478bd9Sstevel@tonic-gate }
6997c478bd9Sstevel@tonic-gate }
7007c478bd9Sstevel@tonic-gate
7017c478bd9Sstevel@tonic-gate #define CACHESIZE 32
7027c478bd9Sstevel@tonic-gate
7037c478bd9Sstevel@tonic-gate struct dinode *
getino(ino_t ino)704*e0dfa398SToomas Soome getino(ino_t ino)
7057c478bd9Sstevel@tonic-gate {
7067c478bd9Sstevel@tonic-gate static ino_t minino, maxino;
7077c478bd9Sstevel@tonic-gate static struct dinode itab[MAXINOPB];
7087c478bd9Sstevel@tonic-gate static struct dinode icache[CACHESIZE];
7097c478bd9Sstevel@tonic-gate static ino_t icacheval[CACHESIZE], lasti = 0;
7107c478bd9Sstevel@tonic-gate static int cacheoff = 0;
7117c478bd9Sstevel@tonic-gate int i;
7127c478bd9Sstevel@tonic-gate
7137c478bd9Sstevel@tonic-gate if (ino >= minino && ino < maxino) {
7147c478bd9Sstevel@tonic-gate lasti = ino;
7157c478bd9Sstevel@tonic-gate return (&itab[ino - minino]);
7167c478bd9Sstevel@tonic-gate }
7177c478bd9Sstevel@tonic-gate
7187c478bd9Sstevel@tonic-gate /* before we do major i/o, check for a secondary cache hit */
7197c478bd9Sstevel@tonic-gate for (i = 0; i < CACHESIZE; i++)
7207c478bd9Sstevel@tonic-gate if (icacheval[i] == ino)
7217c478bd9Sstevel@tonic-gate return (icache + i);
7227c478bd9Sstevel@tonic-gate
7237c478bd9Sstevel@tonic-gate /* we need to do major i/o. throw the last inode retrieved into */
7247c478bd9Sstevel@tonic-gate /* the cache. note: this copies garbage the first time it is */
7257c478bd9Sstevel@tonic-gate /* used, but no harm done. */
7267c478bd9Sstevel@tonic-gate icacheval[cacheoff] = lasti;
7277c478bd9Sstevel@tonic-gate bcopy(itab + (lasti - minino), icache + cacheoff, sizeof (itab[0]));
7287c478bd9Sstevel@tonic-gate lasti = ino;
7297c478bd9Sstevel@tonic-gate if (++cacheoff >= CACHESIZE)
7307c478bd9Sstevel@tonic-gate cacheoff = 0;
7317c478bd9Sstevel@tonic-gate
7327c478bd9Sstevel@tonic-gate #define INOPERDB (DEV_BSIZE / sizeof (struct dinode))
7337c478bd9Sstevel@tonic-gate minino = ino &~ (INOPERDB - 1);
7347c478bd9Sstevel@tonic-gate maxino = ((itog(sblock, ino) + 1) * (unsigned)(sblock->fs_ipg));
7357c478bd9Sstevel@tonic-gate if (maxino > minino + MAXINOPB)
7367c478bd9Sstevel@tonic-gate maxino = minino + MAXINOPB;
7377c478bd9Sstevel@tonic-gate bread(
7387c478bd9Sstevel@tonic-gate /* LINTED: can't make up for broken system macros here */
7397c478bd9Sstevel@tonic-gate (fsbtodb(sblock, itod(sblock, ino)) + itoo(sblock, ino) / INOPERDB),
7407c478bd9Sstevel@tonic-gate /* LINTED: (max - min) * size fits into a size_t */
7417c478bd9Sstevel@tonic-gate (uchar_t *)itab, (size_t)((maxino - minino) * sizeof (*itab)));
7427c478bd9Sstevel@tonic-gate return (&itab[ino - minino]);
7437c478bd9Sstevel@tonic-gate }
7447c478bd9Sstevel@tonic-gate
7457c478bd9Sstevel@tonic-gate #define BREADEMAX 32
7467c478bd9Sstevel@tonic-gate
7477c478bd9Sstevel@tonic-gate #ifdef NO__LONGLONG__
7487c478bd9Sstevel@tonic-gate #define DEV_LSEEK(fd, offset, whence) \
7497c478bd9Sstevel@tonic-gate lseek((fd), (((off_t)(offset))*DEV_BSIZE), (whence))
7507c478bd9Sstevel@tonic-gate #else
7517c478bd9Sstevel@tonic-gate #define DEV_LSEEK(fd, offset, whence) \
75290eb94cfSns158690 llseek((fd), (((offset_t)((offset)))*DEV_BSIZE), (whence))
7537c478bd9Sstevel@tonic-gate #endif
7547c478bd9Sstevel@tonic-gate
7557c478bd9Sstevel@tonic-gate #define BREAD_FAIL(buf, size) { \
7567c478bd9Sstevel@tonic-gate breaderrors += 1; \
7577c478bd9Sstevel@tonic-gate bzero(buf, (size_t)size); \
7587c478bd9Sstevel@tonic-gate }
7597c478bd9Sstevel@tonic-gate
7607c478bd9Sstevel@tonic-gate
7617c478bd9Sstevel@tonic-gate
7627c478bd9Sstevel@tonic-gate void
bread(diskaddr_t da,uchar_t * ba,size_t cnt)763*e0dfa398SToomas Soome bread(diskaddr_t da, uchar_t *ba, size_t cnt)
7647c478bd9Sstevel@tonic-gate {
7657c478bd9Sstevel@tonic-gate caddr_t maddr;
7667c478bd9Sstevel@tonic-gate uchar_t *dest;
7677c478bd9Sstevel@tonic-gate int saverr;
7687c478bd9Sstevel@tonic-gate int n;
7697c478bd9Sstevel@tonic-gate size_t len;
7707c478bd9Sstevel@tonic-gate off64_t filoff;
7717c478bd9Sstevel@tonic-gate off64_t mapoff;
7727c478bd9Sstevel@tonic-gate off64_t displacement;
7737c478bd9Sstevel@tonic-gate
7747c478bd9Sstevel@tonic-gate static size_t pagesize = 0;
7757c478bd9Sstevel@tonic-gate static int breaderrors = 0;
7767c478bd9Sstevel@tonic-gate
7777c478bd9Sstevel@tonic-gate /* mechanics for caching small bread requests. these are */
7787c478bd9Sstevel@tonic-gate /* often small ACLs that are used over and over. */
7797c478bd9Sstevel@tonic-gate static uchar_t bcache[DEV_BSIZE * CACHESIZE];
7807c478bd9Sstevel@tonic-gate static diskaddr_t bcacheval[CACHESIZE];
7817c478bd9Sstevel@tonic-gate static int cacheoff = 0;
7827c478bd9Sstevel@tonic-gate int i;
7837c478bd9Sstevel@tonic-gate
7847c478bd9Sstevel@tonic-gate if ((cnt >= DEV_BSIZE) && (mapfd != -1)) {
7857c478bd9Sstevel@tonic-gate if (pagesize == 0)
7867c478bd9Sstevel@tonic-gate pagesize = getpagesize();
7877c478bd9Sstevel@tonic-gate /*
7887c478bd9Sstevel@tonic-gate * We depend on mmap(2)'s guarantee that mapping a
7897c478bd9Sstevel@tonic-gate * partial page will cause the remainder of the page
7907c478bd9Sstevel@tonic-gate * to be zero-filled.
7917c478bd9Sstevel@tonic-gate */
7927c478bd9Sstevel@tonic-gate filoff = ((off64_t)da) * DEV_BSIZE;
7937c478bd9Sstevel@tonic-gate displacement = filoff & (pagesize - 1);
7947c478bd9Sstevel@tonic-gate mapoff = filoff - displacement;
7957c478bd9Sstevel@tonic-gate /* LINTED offset will fit into 32 bits */
7967c478bd9Sstevel@tonic-gate len = (size_t)roundup(cnt + (filoff - mapoff), pagesize);
7977c478bd9Sstevel@tonic-gate maddr = mmap64(NULL, len, PROT_READ, MAP_SHARED, mapfd, mapoff);
7987c478bd9Sstevel@tonic-gate if (maddr != MAP_FAILED) {
7997c478bd9Sstevel@tonic-gate (void) memcpy(ba, maddr + displacement, cnt);
8007c478bd9Sstevel@tonic-gate (void) munmap(maddr, len);
8017c478bd9Sstevel@tonic-gate return;
8027c478bd9Sstevel@tonic-gate }
8037c478bd9Sstevel@tonic-gate }
8047c478bd9Sstevel@tonic-gate
8057c478bd9Sstevel@tonic-gate if (DEV_LSEEK(fi, da, L_SET) < 0) {
8067c478bd9Sstevel@tonic-gate saverr = errno;
8077c478bd9Sstevel@tonic-gate msg(gettext("bread: dev_seek error: %s\n"), strerror(saverr));
8087c478bd9Sstevel@tonic-gate /* Don't know where we are, return the least-harmful data */
8097c478bd9Sstevel@tonic-gate BREAD_FAIL(ba, cnt);
8107c478bd9Sstevel@tonic-gate return;
8117c478bd9Sstevel@tonic-gate }
8127c478bd9Sstevel@tonic-gate
8137c478bd9Sstevel@tonic-gate if (read(fi, ba, (size_t)cnt) == (size_t)cnt)
8147c478bd9Sstevel@tonic-gate return;
8157c478bd9Sstevel@tonic-gate
8167c478bd9Sstevel@tonic-gate while (cnt != 0) {
8177c478bd9Sstevel@tonic-gate
8187c478bd9Sstevel@tonic-gate if (da >= fsbtodb(sblock, sblock->fs_size)) {
8197c478bd9Sstevel@tonic-gate msg(gettext(
8207c478bd9Sstevel@tonic-gate "Warning - block %llu is beyond the end of `%s'\n"),
8217c478bd9Sstevel@tonic-gate da, disk);
8227c478bd9Sstevel@tonic-gate BREAD_FAIL(ba, cnt);
8237c478bd9Sstevel@tonic-gate break;
8247c478bd9Sstevel@tonic-gate }
8257c478bd9Sstevel@tonic-gate
8267c478bd9Sstevel@tonic-gate if (DEV_LSEEK(fi, da, L_SET) < 0) {
8277c478bd9Sstevel@tonic-gate msg(gettext("%s: %s error\n"), "bread", "DEV_LSEEK2");
8287c478bd9Sstevel@tonic-gate BREAD_FAIL(ba, cnt);
8297c478bd9Sstevel@tonic-gate break;
8307c478bd9Sstevel@tonic-gate }
8317c478bd9Sstevel@tonic-gate
8327c478bd9Sstevel@tonic-gate if (cnt < DEV_BSIZE) {
8337c478bd9Sstevel@tonic-gate /* small read. check for cache hit. */
8347c478bd9Sstevel@tonic-gate for (i = 0; i < CACHESIZE; i++)
8357c478bd9Sstevel@tonic-gate if (bcacheval[i] == da) {
8367c478bd9Sstevel@tonic-gate bcopy(bcache + (i * DEV_BSIZE),
8377c478bd9Sstevel@tonic-gate ba, cnt);
8387c478bd9Sstevel@tonic-gate return;
8397c478bd9Sstevel@tonic-gate }
8407c478bd9Sstevel@tonic-gate
8417c478bd9Sstevel@tonic-gate /* no cache hit; throw this one into the cache... */
8427c478bd9Sstevel@tonic-gate len = cnt;
8437c478bd9Sstevel@tonic-gate dest = bcache + (cacheoff * DEV_BSIZE);
8447c478bd9Sstevel@tonic-gate bcacheval[cacheoff] = da;
8457c478bd9Sstevel@tonic-gate if (++cacheoff >= CACHESIZE)
8467c478bd9Sstevel@tonic-gate cacheoff = 0;
8477c478bd9Sstevel@tonic-gate } else {
8487c478bd9Sstevel@tonic-gate len = DEV_BSIZE;
8497c478bd9Sstevel@tonic-gate dest = ba;
8507c478bd9Sstevel@tonic-gate }
8517c478bd9Sstevel@tonic-gate
8527c478bd9Sstevel@tonic-gate n = read(fi, dest, DEV_BSIZE);
8537c478bd9Sstevel@tonic-gate if (n != DEV_BSIZE) {
8547c478bd9Sstevel@tonic-gate n = MAX(n, 0);
8557c478bd9Sstevel@tonic-gate bzero(dest+n, DEV_BSIZE-n);
8567c478bd9Sstevel@tonic-gate breaderrors += 1;
8577c478bd9Sstevel@tonic-gate msg(gettext(
8587c478bd9Sstevel@tonic-gate "Warning - cannot read sector %llu of `%s'\n"),
8597c478bd9Sstevel@tonic-gate da, disk);
8607c478bd9Sstevel@tonic-gate }
8617c478bd9Sstevel@tonic-gate if (dest != ba)
8627c478bd9Sstevel@tonic-gate bcopy(dest, ba, len);
8637c478bd9Sstevel@tonic-gate
8647c478bd9Sstevel@tonic-gate da++;
8657c478bd9Sstevel@tonic-gate /* LINTED character pointers aren't signed */
8667c478bd9Sstevel@tonic-gate ba += len;
8677c478bd9Sstevel@tonic-gate cnt -= len;
8687c478bd9Sstevel@tonic-gate }
8697c478bd9Sstevel@tonic-gate
8707c478bd9Sstevel@tonic-gate if (breaderrors > BREADEMAX) {
8717c478bd9Sstevel@tonic-gate msg(gettext(
8727c478bd9Sstevel@tonic-gate "More than %d block read errors from dump device `%s'\n"),
8737c478bd9Sstevel@tonic-gate BREADEMAX, disk);
8747c478bd9Sstevel@tonic-gate dumpailing();
8757c478bd9Sstevel@tonic-gate breaderrors = 0;
8767c478bd9Sstevel@tonic-gate }
8777c478bd9Sstevel@tonic-gate }
878