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