1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 1996, 1998, 2001-2003 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 7*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 8*7c478bd9Sstevel@tonic-gate 9*7c478bd9Sstevel@tonic-gate /* 10*7c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 11*7c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 12*7c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 13*7c478bd9Sstevel@tonic-gate */ 14*7c478bd9Sstevel@tonic-gate 15*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 16*7c478bd9Sstevel@tonic-gate 17*7c478bd9Sstevel@tonic-gate #include "dump.h" 18*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 19*7c478bd9Sstevel@tonic-gate #include <sys/mman.h> 20*7c478bd9Sstevel@tonic-gate 21*7c478bd9Sstevel@tonic-gate #ifdef __STDC__ 22*7c478bd9Sstevel@tonic-gate static void lf_dmpindir(daddr32_t, int, u_offset_t *); 23*7c478bd9Sstevel@tonic-gate static void indir(daddr32_t, int, u_offset_t *); 24*7c478bd9Sstevel@tonic-gate static void lf_blksout(daddr32_t *, u_offset_t); 25*7c478bd9Sstevel@tonic-gate static void lf_dumpinode(struct dinode *); 26*7c478bd9Sstevel@tonic-gate static void dsrch(daddr32_t, ulong_t, u_offset_t); 27*7c478bd9Sstevel@tonic-gate void lf_dump(struct dinode *); 28*7c478bd9Sstevel@tonic-gate #else 29*7c478bd9Sstevel@tonic-gate static void lf_dmpindir(); 30*7c478bd9Sstevel@tonic-gate static void indir(); 31*7c478bd9Sstevel@tonic-gate static void lf_blksout(); 32*7c478bd9Sstevel@tonic-gate static void dsrch(); 33*7c478bd9Sstevel@tonic-gate void lf_dump(); 34*7c478bd9Sstevel@tonic-gate #endif 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate static char msgbuf[256]; 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate void 39*7c478bd9Sstevel@tonic-gate pass(fn, map) 40*7c478bd9Sstevel@tonic-gate void (*fn)(struct dinode *); 41*7c478bd9Sstevel@tonic-gate uchar_t *map; 42*7c478bd9Sstevel@tonic-gate { 43*7c478bd9Sstevel@tonic-gate int bits; 44*7c478bd9Sstevel@tonic-gate ino_t maxino; 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate maxino = (unsigned)(sblock->fs_ipg * sblock->fs_ncg - 1); 47*7c478bd9Sstevel@tonic-gate /* 48*7c478bd9Sstevel@tonic-gate * Handle pass restarts. We don't check for UFSROOTINO just in 49*7c478bd9Sstevel@tonic-gate * case we need to restart on the root inode. 50*7c478bd9Sstevel@tonic-gate */ 51*7c478bd9Sstevel@tonic-gate if (ino != 0) { 52*7c478bd9Sstevel@tonic-gate bits = ~0; 53*7c478bd9Sstevel@tonic-gate if (map != NULL) { 54*7c478bd9Sstevel@tonic-gate /* LINTED: lint seems to think map is signed */ 55*7c478bd9Sstevel@tonic-gate map += (ino / NBBY); 56*7c478bd9Sstevel@tonic-gate bits = *map++; 57*7c478bd9Sstevel@tonic-gate } 58*7c478bd9Sstevel@tonic-gate bits >>= (ino % NBBY); 59*7c478bd9Sstevel@tonic-gate resetino(ino); 60*7c478bd9Sstevel@tonic-gate goto restart; 61*7c478bd9Sstevel@tonic-gate } 62*7c478bd9Sstevel@tonic-gate while (ino < maxino) { 63*7c478bd9Sstevel@tonic-gate if ((ino % NBBY) == 0) { 64*7c478bd9Sstevel@tonic-gate bits = ~0; 65*7c478bd9Sstevel@tonic-gate if (map != NULL) 66*7c478bd9Sstevel@tonic-gate bits = *map++; 67*7c478bd9Sstevel@tonic-gate } 68*7c478bd9Sstevel@tonic-gate restart: 69*7c478bd9Sstevel@tonic-gate ino++; 70*7c478bd9Sstevel@tonic-gate /* 71*7c478bd9Sstevel@tonic-gate * Ignore any inode less than UFSROOTINO and inodes that 72*7c478bd9Sstevel@tonic-gate * we have already done on a previous pass. 73*7c478bd9Sstevel@tonic-gate */ 74*7c478bd9Sstevel@tonic-gate if ((ino >= UFSROOTINO) && (bits & 1)) { 75*7c478bd9Sstevel@tonic-gate /* 76*7c478bd9Sstevel@tonic-gate * The following test is merely an optimization 77*7c478bd9Sstevel@tonic-gate * for common case where "add" will just return. 78*7c478bd9Sstevel@tonic-gate */ 79*7c478bd9Sstevel@tonic-gate if (!(fn == add && BIT(ino, nodmap))) 80*7c478bd9Sstevel@tonic-gate (*fn)(getino(ino)); 81*7c478bd9Sstevel@tonic-gate } 82*7c478bd9Sstevel@tonic-gate bits >>= 1; 83*7c478bd9Sstevel@tonic-gate } 84*7c478bd9Sstevel@tonic-gate } 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate void 87*7c478bd9Sstevel@tonic-gate mark(ip) 88*7c478bd9Sstevel@tonic-gate struct dinode *ip; 89*7c478bd9Sstevel@tonic-gate { 90*7c478bd9Sstevel@tonic-gate int f; 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate f = ip->di_mode & IFMT; 93*7c478bd9Sstevel@tonic-gate if (f == 0 || ip->di_nlink <= 0) { 94*7c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */ 95*7c478bd9Sstevel@tonic-gate BIC(ino, clrmap); 96*7c478bd9Sstevel@tonic-gate return; 97*7c478bd9Sstevel@tonic-gate } 98*7c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */ 99*7c478bd9Sstevel@tonic-gate BIS(ino, clrmap); 100*7c478bd9Sstevel@tonic-gate if (f == IFDIR || f == IFATTRDIR) { 101*7c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */ 102*7c478bd9Sstevel@tonic-gate BIS(ino, dirmap); 103*7c478bd9Sstevel@tonic-gate } 104*7c478bd9Sstevel@tonic-gate if (ip->di_ctime >= spcl.c_ddate) { 105*7c478bd9Sstevel@tonic-gate if (f == IFSHAD) 106*7c478bd9Sstevel@tonic-gate return; 107*7c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */ 108*7c478bd9Sstevel@tonic-gate BIS(ino, nodmap); 109*7c478bd9Sstevel@tonic-gate /* attribute changes impact the root */ 110*7c478bd9Sstevel@tonic-gate if (f == IFATTRDIR) 111*7c478bd9Sstevel@tonic-gate BIS(UFSROOTINO, nodmap); 112*7c478bd9Sstevel@tonic-gate if (f != IFREG && f != IFDIR && f != IFATTRDIR && f != IFLNK) { 113*7c478bd9Sstevel@tonic-gate o_esize += 1; 114*7c478bd9Sstevel@tonic-gate return; 115*7c478bd9Sstevel@tonic-gate } 116*7c478bd9Sstevel@tonic-gate est(ip); 117*7c478bd9Sstevel@tonic-gate } 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate void 121*7c478bd9Sstevel@tonic-gate active_mark(ip) 122*7c478bd9Sstevel@tonic-gate struct dinode *ip; 123*7c478bd9Sstevel@tonic-gate { 124*7c478bd9Sstevel@tonic-gate int f; 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate f = ip->di_mode & IFMT; 127*7c478bd9Sstevel@tonic-gate if (f == 0 || ip->di_nlink <= 0) { 128*7c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */ 129*7c478bd9Sstevel@tonic-gate BIC(ino, clrmap); 130*7c478bd9Sstevel@tonic-gate return; 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */ 133*7c478bd9Sstevel@tonic-gate BIS(ino, clrmap); 134*7c478bd9Sstevel@tonic-gate if (f == IFDIR || f == IFATTRDIR) { 135*7c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */ 136*7c478bd9Sstevel@tonic-gate BIS(ino, dirmap); 137*7c478bd9Sstevel@tonic-gate } 138*7c478bd9Sstevel@tonic-gate if (BIT(ino, activemap)) { 139*7c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */ 140*7c478bd9Sstevel@tonic-gate BIS(ino, nodmap); 141*7c478bd9Sstevel@tonic-gate /* attribute changes impact the root */ 142*7c478bd9Sstevel@tonic-gate if (f == IFATTRDIR) 143*7c478bd9Sstevel@tonic-gate BIS(UFSROOTINO, nodmap); 144*7c478bd9Sstevel@tonic-gate if (f != IFREG && f != IFDIR && f != IFATTRDIR && f != IFLNK) { 145*7c478bd9Sstevel@tonic-gate o_esize += 1; 146*7c478bd9Sstevel@tonic-gate return; 147*7c478bd9Sstevel@tonic-gate } 148*7c478bd9Sstevel@tonic-gate est(ip); 149*7c478bd9Sstevel@tonic-gate } 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate static struct shcount { 153*7c478bd9Sstevel@tonic-gate struct shcount *higher, *lower; 154*7c478bd9Sstevel@tonic-gate ino_t ino; 155*7c478bd9Sstevel@tonic-gate unsigned long count; 156*7c478bd9Sstevel@tonic-gate } shcounts = { 157*7c478bd9Sstevel@tonic-gate NULL, NULL, 158*7c478bd9Sstevel@tonic-gate 0, 159*7c478bd9Sstevel@tonic-gate 0 160*7c478bd9Sstevel@tonic-gate }; 161*7c478bd9Sstevel@tonic-gate static struct shcount *shc = NULL; 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate void 164*7c478bd9Sstevel@tonic-gate markshad(ip) 165*7c478bd9Sstevel@tonic-gate struct dinode *ip; 166*7c478bd9Sstevel@tonic-gate { 167*7c478bd9Sstevel@tonic-gate ino_t shadow; 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate if (ip->di_shadow == 0) 170*7c478bd9Sstevel@tonic-gate return; 171*7c478bd9Sstevel@tonic-gate if (shc == NULL) 172*7c478bd9Sstevel@tonic-gate shc = &shcounts; 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate shadow = (ino_t)(unsigned)(ip->di_shadow); 175*7c478bd9Sstevel@tonic-gate while ((shadow > shc->ino) && (shc->higher)) 176*7c478bd9Sstevel@tonic-gate shc = shc->higher; 177*7c478bd9Sstevel@tonic-gate while ((shadow < shc->ino) && (shc->lower)) 178*7c478bd9Sstevel@tonic-gate shc = shc->lower; 179*7c478bd9Sstevel@tonic-gate if (shadow != shc->ino) { 180*7c478bd9Sstevel@tonic-gate struct shcount *new; 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate new = (struct shcount *)xcalloc(1, sizeof (*new)); 183*7c478bd9Sstevel@tonic-gate new->higher = shc->higher; 184*7c478bd9Sstevel@tonic-gate if (shc->higher != NULL) 185*7c478bd9Sstevel@tonic-gate shc->higher->lower = new; 186*7c478bd9Sstevel@tonic-gate shc->higher = new; 187*7c478bd9Sstevel@tonic-gate new->lower = shc; 188*7c478bd9Sstevel@tonic-gate shc = new; 189*7c478bd9Sstevel@tonic-gate shc->ino = shadow; 190*7c478bd9Sstevel@tonic-gate } 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */ 193*7c478bd9Sstevel@tonic-gate BIS(shadow, shamap); 194*7c478bd9Sstevel@tonic-gate shc->count++; 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate void 198*7c478bd9Sstevel@tonic-gate estshad(ip) 199*7c478bd9Sstevel@tonic-gate struct dinode *ip; 200*7c478bd9Sstevel@tonic-gate { 201*7c478bd9Sstevel@tonic-gate u_offset_t esizeprime; 202*7c478bd9Sstevel@tonic-gate u_offset_t tmpesize; 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate if (ip->di_size <= sizeof (union u_shadow)) 205*7c478bd9Sstevel@tonic-gate return; 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate while ((ino > shc->ino) && (shc->higher)) 208*7c478bd9Sstevel@tonic-gate shc = shc->higher; 209*7c478bd9Sstevel@tonic-gate while ((ino < shc->ino) && (shc->lower)) 210*7c478bd9Sstevel@tonic-gate shc = shc->lower; 211*7c478bd9Sstevel@tonic-gate if (ino != shc->ino) 212*7c478bd9Sstevel@tonic-gate return; /* xxx panic? complain? */ 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate tmpesize = (o_esize + f_esize); 215*7c478bd9Sstevel@tonic-gate esizeprime = tmpesize; 216*7c478bd9Sstevel@tonic-gate est(ip); 217*7c478bd9Sstevel@tonic-gate esizeprime = tmpesize - esizeprime; 218*7c478bd9Sstevel@tonic-gate esizeprime *= shc->count - 1; 219*7c478bd9Sstevel@tonic-gate f_esize += esizeprime; 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate void 223*7c478bd9Sstevel@tonic-gate freeshad() 224*7c478bd9Sstevel@tonic-gate { 225*7c478bd9Sstevel@tonic-gate if (shc == NULL) 226*7c478bd9Sstevel@tonic-gate return; 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate while (shc->higher) 229*7c478bd9Sstevel@tonic-gate shc = shc->higher; 230*7c478bd9Sstevel@tonic-gate while (shc->lower) { 231*7c478bd9Sstevel@tonic-gate shc = shc->lower; 232*7c478bd9Sstevel@tonic-gate if (shc->higher) /* else panic? */ 233*7c478bd9Sstevel@tonic-gate (void) free(shc->higher); 234*7c478bd9Sstevel@tonic-gate } 235*7c478bd9Sstevel@tonic-gate /* 236*7c478bd9Sstevel@tonic-gate * This should be unnecessary, but do it just to be safe. 237*7c478bd9Sstevel@tonic-gate * Note that shc might be malloc'd or static, so can't free(). 238*7c478bd9Sstevel@tonic-gate */ 239*7c478bd9Sstevel@tonic-gate bzero(shc, sizeof (*shc)); 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate void 243*7c478bd9Sstevel@tonic-gate add(ip) 244*7c478bd9Sstevel@tonic-gate struct dinode *ip; 245*7c478bd9Sstevel@tonic-gate { 246*7c478bd9Sstevel@tonic-gate int i; 247*7c478bd9Sstevel@tonic-gate u_offset_t filesize; 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate if (BIT(ino, nodmap)) 250*7c478bd9Sstevel@tonic-gate return; 251*7c478bd9Sstevel@tonic-gate if ((ip->di_mode & IFMT) != IFDIR && 252*7c478bd9Sstevel@tonic-gate (ip->di_mode & IFMT) != IFATTRDIR) { 253*7c478bd9Sstevel@tonic-gate (void) snprintf(msgbuf, sizeof (msgbuf), gettext( 254*7c478bd9Sstevel@tonic-gate "Warning - directory at inode `%lu' vanished!\n"), ino); 255*7c478bd9Sstevel@tonic-gate msg(msgbuf); 256*7c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */ 257*7c478bd9Sstevel@tonic-gate BIC(ino, dirmap); 258*7c478bd9Sstevel@tonic-gate return; 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate nsubdir = 0; 261*7c478bd9Sstevel@tonic-gate dadded = 0; 262*7c478bd9Sstevel@tonic-gate filesize = ip->di_size; 263*7c478bd9Sstevel@tonic-gate for (i = 0; i < NDADDR; i++) { 264*7c478bd9Sstevel@tonic-gate if (ip->di_db[i] != 0) 265*7c478bd9Sstevel@tonic-gate /* LINTED dblksize/blkoff does a safe cast here */ 266*7c478bd9Sstevel@tonic-gate dsrch(ip->di_db[i], (ulong_t)dblksize(sblock, ip, i), 267*7c478bd9Sstevel@tonic-gate filesize); 268*7c478bd9Sstevel@tonic-gate filesize -= (unsigned)(sblock->fs_bsize); 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate for (i = 0; i < NIADDR; i++) { 271*7c478bd9Sstevel@tonic-gate if (ip->di_ib[i] != 0) 272*7c478bd9Sstevel@tonic-gate indir(ip->di_ib[i], i, &filesize); 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate if (dadded) { 275*7c478bd9Sstevel@tonic-gate nadded++; 276*7c478bd9Sstevel@tonic-gate if (!BIT(ino, nodmap)) { 277*7c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */ 278*7c478bd9Sstevel@tonic-gate BIS(ino, nodmap); 279*7c478bd9Sstevel@tonic-gate if ((ip->di_mode & IFMT) == IFATTRDIR) { 280*7c478bd9Sstevel@tonic-gate /* attribute changes "auto-percolate" to root */ 281*7c478bd9Sstevel@tonic-gate BIS(UFSROOTINO, nodmap); 282*7c478bd9Sstevel@tonic-gate } 283*7c478bd9Sstevel@tonic-gate est(ip); 284*7c478bd9Sstevel@tonic-gate } 285*7c478bd9Sstevel@tonic-gate } 286*7c478bd9Sstevel@tonic-gate if (nsubdir == 0) { 287*7c478bd9Sstevel@tonic-gate if (!BIT(ino, nodmap)) { 288*7c478bd9Sstevel@tonic-gate /* LINTED: 32-bit to 8-bit assignment ok */ 289*7c478bd9Sstevel@tonic-gate BIC(ino, dirmap); 290*7c478bd9Sstevel@tonic-gate } 291*7c478bd9Sstevel@tonic-gate } 292*7c478bd9Sstevel@tonic-gate } 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate static void 295*7c478bd9Sstevel@tonic-gate indir(d, n, filesize) 296*7c478bd9Sstevel@tonic-gate daddr32_t d; 297*7c478bd9Sstevel@tonic-gate int n; 298*7c478bd9Sstevel@tonic-gate u_offset_t *filesize; 299*7c478bd9Sstevel@tonic-gate { 300*7c478bd9Sstevel@tonic-gate int i; 301*7c478bd9Sstevel@tonic-gate daddr32_t idblk[MAXNINDIR]; 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate if ((unsigned)(sblock->fs_bsize) > sizeof (idblk)) { 304*7c478bd9Sstevel@tonic-gate msg(gettext( 305*7c478bd9Sstevel@tonic-gate "Inconsistency detected: filesystem block size larger than valid maximum.\n")); 306*7c478bd9Sstevel@tonic-gate dumpabort(); 307*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate if ((unsigned)NINDIR(sblock) > MAXNINDIR) { 311*7c478bd9Sstevel@tonic-gate /*CSTYLED*/ 312*7c478bd9Sstevel@tonic-gate msg(gettext( 313*7c478bd9Sstevel@tonic-gate "Inconsistency detected: inode has more indirect \ 314*7c478bd9Sstevel@tonic-gate blocks than valid maximum.\n")); 315*7c478bd9Sstevel@tonic-gate dumpabort(); 316*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate if (dadded || *filesize == 0) 320*7c478bd9Sstevel@tonic-gate return; 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate #ifdef lint 323*7c478bd9Sstevel@tonic-gate idblk[0] = '\0'; 324*7c478bd9Sstevel@tonic-gate #endif /* lint */ 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate /* xxx sanity check sblock contents before trusting them */ 327*7c478bd9Sstevel@tonic-gate bread(fsbtodb(sblock, d), (uchar_t *)idblk, (size_t)sblock->fs_bsize); 328*7c478bd9Sstevel@tonic-gate if (n <= 0) { 329*7c478bd9Sstevel@tonic-gate for (i = 0; i < NINDIR(sblock); i++) { 330*7c478bd9Sstevel@tonic-gate d = idblk[i]; 331*7c478bd9Sstevel@tonic-gate if (d != 0) 332*7c478bd9Sstevel@tonic-gate dsrch(d, (ulong_t)(uint32_t)sblock->fs_bsize, 333*7c478bd9Sstevel@tonic-gate *filesize); 334*7c478bd9Sstevel@tonic-gate *filesize -= (unsigned)(sblock->fs_bsize); 335*7c478bd9Sstevel@tonic-gate } 336*7c478bd9Sstevel@tonic-gate } else { 337*7c478bd9Sstevel@tonic-gate n--; 338*7c478bd9Sstevel@tonic-gate for (i = 0; i < NINDIR(sblock); i++) { 339*7c478bd9Sstevel@tonic-gate d = idblk[i]; 340*7c478bd9Sstevel@tonic-gate if (d != 0) 341*7c478bd9Sstevel@tonic-gate indir(d, n, filesize); 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate void 347*7c478bd9Sstevel@tonic-gate dirdump(ip) 348*7c478bd9Sstevel@tonic-gate struct dinode *ip; 349*7c478bd9Sstevel@tonic-gate { 350*7c478bd9Sstevel@tonic-gate /* watchout for dir inodes deleted and maybe reallocated */ 351*7c478bd9Sstevel@tonic-gate if (((ip->di_mode & IFMT) != IFDIR && 352*7c478bd9Sstevel@tonic-gate (ip->di_mode & IFMT) != IFATTRDIR) || ip->di_nlink < 2) { 353*7c478bd9Sstevel@tonic-gate (void) snprintf(msgbuf, sizeof (msgbuf), gettext( 354*7c478bd9Sstevel@tonic-gate "Warning - directory at inode `%lu' vanished!\n"), 355*7c478bd9Sstevel@tonic-gate ino); 356*7c478bd9Sstevel@tonic-gate msg(msgbuf); 357*7c478bd9Sstevel@tonic-gate return; 358*7c478bd9Sstevel@tonic-gate } 359*7c478bd9Sstevel@tonic-gate lf_dump(ip); 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate static u_offset_t loffset; /* current offset in file (ufsdump) */ 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate static void 365*7c478bd9Sstevel@tonic-gate lf_dumpmeta(ip) 366*7c478bd9Sstevel@tonic-gate struct dinode *ip; 367*7c478bd9Sstevel@tonic-gate { 368*7c478bd9Sstevel@tonic-gate if ((ip->di_shadow == 0) || shortmeta) 369*7c478bd9Sstevel@tonic-gate return; 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate lf_dumpinode(getino((ino_t)(unsigned)(ip->di_shadow))); 372*7c478bd9Sstevel@tonic-gate } 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate int 375*7c478bd9Sstevel@tonic-gate hasshortmeta(ip) 376*7c478bd9Sstevel@tonic-gate struct dinode **ip; 377*7c478bd9Sstevel@tonic-gate { 378*7c478bd9Sstevel@tonic-gate ino_t savino; 379*7c478bd9Sstevel@tonic-gate int rc; 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate if ((*ip)->di_shadow == 0) 382*7c478bd9Sstevel@tonic-gate return (0); 383*7c478bd9Sstevel@tonic-gate savino = ino; 384*7c478bd9Sstevel@tonic-gate *ip = getino((ino_t)(unsigned)((*ip)->di_shadow)); 385*7c478bd9Sstevel@tonic-gate rc = ((*ip)->di_size <= sizeof (union u_shadow)); 386*7c478bd9Sstevel@tonic-gate *ip = getino(ino = savino); 387*7c478bd9Sstevel@tonic-gate return (rc); 388*7c478bd9Sstevel@tonic-gate } 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate void 391*7c478bd9Sstevel@tonic-gate lf_dumpinode(ip) 392*7c478bd9Sstevel@tonic-gate struct dinode *ip; 393*7c478bd9Sstevel@tonic-gate { 394*7c478bd9Sstevel@tonic-gate int i; 395*7c478bd9Sstevel@tonic-gate u_offset_t size; 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate i = ip->di_mode & IFMT; 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate if (i == 0 || ip->di_nlink <= 0) 400*7c478bd9Sstevel@tonic-gate return; 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate spcl.c_dinode = *ip; 403*7c478bd9Sstevel@tonic-gate spcl.c_count = 0; 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate if ((i != IFDIR && i != IFATTRDIR && i != IFREG && i != IFLNK && 406*7c478bd9Sstevel@tonic-gate i != IFSHAD) || ip->di_size == 0) { 407*7c478bd9Sstevel@tonic-gate toslave(dospcl, ino); 408*7c478bd9Sstevel@tonic-gate return; 409*7c478bd9Sstevel@tonic-gate } 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate size = NDADDR * (unsigned)(sblock->fs_bsize); 412*7c478bd9Sstevel@tonic-gate if (size > ip->di_size) 413*7c478bd9Sstevel@tonic-gate size = ip->di_size; 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate lf_blksout(&ip->di_db[0], size); 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate size = ip->di_size - size; 418*7c478bd9Sstevel@tonic-gate if (size > 0) { 419*7c478bd9Sstevel@tonic-gate for (i = 0; i < NIADDR; i++) { 420*7c478bd9Sstevel@tonic-gate lf_dmpindir(ip->di_ib[i], i, &size); 421*7c478bd9Sstevel@tonic-gate if (size == 0) 422*7c478bd9Sstevel@tonic-gate break; 423*7c478bd9Sstevel@tonic-gate } 424*7c478bd9Sstevel@tonic-gate } 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate void 428*7c478bd9Sstevel@tonic-gate lf_dump(ip) 429*7c478bd9Sstevel@tonic-gate struct dinode *ip; 430*7c478bd9Sstevel@tonic-gate { 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate if ((!BIT(ino, nodmap)) && (!BIT(ino, shamap))) 433*7c478bd9Sstevel@tonic-gate return; 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate shortmeta = hasshortmeta(&ip); 436*7c478bd9Sstevel@tonic-gate if (shortmeta) { 437*7c478bd9Sstevel@tonic-gate ip = getino((ino_t)(unsigned)(ip->di_shadow)); 438*7c478bd9Sstevel@tonic-gate /* assume spcl.c_shadow is smaller than 1 block */ 439*7c478bd9Sstevel@tonic-gate bread(fsbtodb(sblock, ip->di_db[0]), 440*7c478bd9Sstevel@tonic-gate (uchar_t *)spcl.c_shadow.c_shadow, sizeof (spcl.c_shadow)); 441*7c478bd9Sstevel@tonic-gate spcl.c_flags |= DR_HASMETA; 442*7c478bd9Sstevel@tonic-gate } else { 443*7c478bd9Sstevel@tonic-gate spcl.c_flags &= ~DR_HASMETA; 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate ip = getino(ino); 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate loffset = 0; 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate if (newtape) { 450*7c478bd9Sstevel@tonic-gate spcl.c_type = TS_TAPE; 451*7c478bd9Sstevel@tonic-gate } else if (pos) 452*7c478bd9Sstevel@tonic-gate spcl.c_type = TS_ADDR; 453*7c478bd9Sstevel@tonic-gate else 454*7c478bd9Sstevel@tonic-gate spcl.c_type = TS_INODE; 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate newtape = 0; 457*7c478bd9Sstevel@tonic-gate lf_dumpinode(ip); 458*7c478bd9Sstevel@tonic-gate lf_dumpmeta(ip); 459*7c478bd9Sstevel@tonic-gate pos = 0; 460*7c478bd9Sstevel@tonic-gate } 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate static void 463*7c478bd9Sstevel@tonic-gate lf_dmpindir(blk, lvl, size) 464*7c478bd9Sstevel@tonic-gate daddr32_t blk; 465*7c478bd9Sstevel@tonic-gate int lvl; 466*7c478bd9Sstevel@tonic-gate u_offset_t *size; 467*7c478bd9Sstevel@tonic-gate { 468*7c478bd9Sstevel@tonic-gate int i; 469*7c478bd9Sstevel@tonic-gate u_offset_t cnt; 470*7c478bd9Sstevel@tonic-gate daddr32_t idblk[MAXNINDIR]; 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate if ((unsigned)(sblock->fs_bsize) > sizeof (idblk)) { 473*7c478bd9Sstevel@tonic-gate msg(gettext( 474*7c478bd9Sstevel@tonic-gate "Inconsistency detected: filesystem block size larger than valid maximum.\n")); 475*7c478bd9Sstevel@tonic-gate dumpabort(); 476*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 477*7c478bd9Sstevel@tonic-gate } 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate if ((unsigned)NINDIR(sblock) > MAXNINDIR) { 480*7c478bd9Sstevel@tonic-gate msg(gettext( 481*7c478bd9Sstevel@tonic-gate "Inconsistency detected: inode has more indirect \ 482*7c478bd9Sstevel@tonic-gate blocks than valid maximum.\n")); 483*7c478bd9Sstevel@tonic-gate dumpabort(); 484*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 485*7c478bd9Sstevel@tonic-gate } 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate if (blk != 0) 488*7c478bd9Sstevel@tonic-gate bread(fsbtodb(sblock, blk), (uchar_t *)idblk, 489*7c478bd9Sstevel@tonic-gate (size_t)sblock->fs_bsize); 490*7c478bd9Sstevel@tonic-gate else 491*7c478bd9Sstevel@tonic-gate bzero((char *)idblk, (size_t)sblock->fs_bsize); 492*7c478bd9Sstevel@tonic-gate if (lvl <= 0) { 493*7c478bd9Sstevel@tonic-gate cnt = (u_offset_t)(unsigned)NINDIR(sblock) * 494*7c478bd9Sstevel@tonic-gate (u_offset_t)(unsigned)(sblock->fs_bsize); 495*7c478bd9Sstevel@tonic-gate if (cnt > *size) 496*7c478bd9Sstevel@tonic-gate cnt = *size; 497*7c478bd9Sstevel@tonic-gate *size -= cnt; 498*7c478bd9Sstevel@tonic-gate lf_blksout(&idblk[0], cnt); 499*7c478bd9Sstevel@tonic-gate return; 500*7c478bd9Sstevel@tonic-gate } 501*7c478bd9Sstevel@tonic-gate lvl--; 502*7c478bd9Sstevel@tonic-gate for (i = 0; i < NINDIR(sblock); i++) { 503*7c478bd9Sstevel@tonic-gate lf_dmpindir(idblk[i], lvl, size); 504*7c478bd9Sstevel@tonic-gate if (*size == 0) 505*7c478bd9Sstevel@tonic-gate return; 506*7c478bd9Sstevel@tonic-gate } 507*7c478bd9Sstevel@tonic-gate } 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate static void 510*7c478bd9Sstevel@tonic-gate lf_blksout(blkp, bytes) 511*7c478bd9Sstevel@tonic-gate daddr32_t *blkp; 512*7c478bd9Sstevel@tonic-gate u_offset_t bytes; 513*7c478bd9Sstevel@tonic-gate { 514*7c478bd9Sstevel@tonic-gate u_offset_t i; 515*7c478bd9Sstevel@tonic-gate u_offset_t tbperfsb = (unsigned)(sblock->fs_bsize / tp_bsize); 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate u_offset_t j, k, count; 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate u_offset_t bytepos, diff; 520*7c478bd9Sstevel@tonic-gate u_offset_t bytecnt = 0; 521*7c478bd9Sstevel@tonic-gate off_t byteoff = 0; /* bytes to skip within first f/s block */ 522*7c478bd9Sstevel@tonic-gate off_t fragoff = 0; /* frags to skip within first f/s block */ 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate u_offset_t tpblkoff = 0; /* tape blocks to skip in first f/s block */ 525*7c478bd9Sstevel@tonic-gate u_offset_t tpblkskip = 0; /* total tape blocks to skip */ 526*7c478bd9Sstevel@tonic-gate u_offset_t skip; /* tape blocks to skip this pass */ 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate if (pos) { 529*7c478bd9Sstevel@tonic-gate /* 530*7c478bd9Sstevel@tonic-gate * We get here if a slave throws a signal to the 531*7c478bd9Sstevel@tonic-gate * master indicating a partially dumped file. 532*7c478bd9Sstevel@tonic-gate * Begin by figuring out what was undone. 533*7c478bd9Sstevel@tonic-gate */ 534*7c478bd9Sstevel@tonic-gate bytepos = (offset_t)pos * tp_bsize; 535*7c478bd9Sstevel@tonic-gate 536*7c478bd9Sstevel@tonic-gate if ((loffset + bytes) <= bytepos) { 537*7c478bd9Sstevel@tonic-gate /* This stuff was dumped already, forget it. */ 538*7c478bd9Sstevel@tonic-gate loffset += (u_offset_t)tp_bsize * 539*7c478bd9Sstevel@tonic-gate /* LINTED: spurious complaint on sign-extending */ 540*7c478bd9Sstevel@tonic-gate d_howmany(bytes, (u_offset_t)tp_bsize); 541*7c478bd9Sstevel@tonic-gate return; 542*7c478bd9Sstevel@tonic-gate } 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate if (loffset < bytepos) { 545*7c478bd9Sstevel@tonic-gate /* 546*7c478bd9Sstevel@tonic-gate * Some of this was dumped, some wasn't. 547*7c478bd9Sstevel@tonic-gate * Figure out what was done and skip it. 548*7c478bd9Sstevel@tonic-gate */ 549*7c478bd9Sstevel@tonic-gate diff = bytepos - loffset; 550*7c478bd9Sstevel@tonic-gate /* LINTED: spurious complaint on sign-extending */ 551*7c478bd9Sstevel@tonic-gate tpblkskip = d_howmany(diff, (u_offset_t)tp_bsize); 552*7c478bd9Sstevel@tonic-gate /* LINTED room after EOT is only a few MB */ 553*7c478bd9Sstevel@tonic-gate blkp += (int)(diff / sblock->fs_bsize); 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate bytecnt = diff % (unsigned)(sblock->fs_bsize); 556*7c478bd9Sstevel@tonic-gate /* LINTED: result fits, due to modulus */ 557*7c478bd9Sstevel@tonic-gate byteoff = bytecnt % (off_t)(sblock->fs_fsize); 558*7c478bd9Sstevel@tonic-gate /* LINTED: spurious complaint on sign-extending */ 559*7c478bd9Sstevel@tonic-gate tpblkoff = d_howmany(bytecnt, 560*7c478bd9Sstevel@tonic-gate (u_offset_t)(unsigned)tp_bsize); 561*7c478bd9Sstevel@tonic-gate /* LINTED: result fits, due to modulus */ 562*7c478bd9Sstevel@tonic-gate fragoff = bytecnt / (off_t)(sblock->fs_fsize); 563*7c478bd9Sstevel@tonic-gate bytecnt = (unsigned)(sblock->fs_bsize) - bytecnt; 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate } 566*7c478bd9Sstevel@tonic-gate 567*7c478bd9Sstevel@tonic-gate loffset += bytes; 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate while (bytes > 0) { 570*7c478bd9Sstevel@tonic-gate if (bytes < TP_NINDIR*tp_bsize) 571*7c478bd9Sstevel@tonic-gate /* LINTED: spurious complaint on sign-extending */ 572*7c478bd9Sstevel@tonic-gate count = d_howmany(bytes, (u_offset_t)tp_bsize); 573*7c478bd9Sstevel@tonic-gate else 574*7c478bd9Sstevel@tonic-gate count = TP_NINDIR; 575*7c478bd9Sstevel@tonic-gate if (tpblkskip) { 576*7c478bd9Sstevel@tonic-gate if (tpblkskip < TP_NINDIR) { 577*7c478bd9Sstevel@tonic-gate bytes -= (tpblkskip * (u_offset_t)tp_bsize); 578*7c478bd9Sstevel@tonic-gate skip = tpblkskip; 579*7c478bd9Sstevel@tonic-gate tpblkskip = 0; 580*7c478bd9Sstevel@tonic-gate } else { 581*7c478bd9Sstevel@tonic-gate bytes -= (offset_t)TP_NINDIR*tp_bsize; 582*7c478bd9Sstevel@tonic-gate tpblkskip -= TP_NINDIR; 583*7c478bd9Sstevel@tonic-gate continue; 584*7c478bd9Sstevel@tonic-gate } 585*7c478bd9Sstevel@tonic-gate } else 586*7c478bd9Sstevel@tonic-gate skip = 0; 587*7c478bd9Sstevel@tonic-gate assert(tbperfsb >= tpblkoff); 588*7c478bd9Sstevel@tonic-gate assert((count - skip) <= TP_NINDIR); 589*7c478bd9Sstevel@tonic-gate for (j = 0, k = 0; j < count - skip; j++, k++) { 590*7c478bd9Sstevel@tonic-gate spcl.c_addr[j] = (blkp[k] != 0); 591*7c478bd9Sstevel@tonic-gate for (i = tbperfsb - tpblkoff; --i > 0; j++) 592*7c478bd9Sstevel@tonic-gate spcl.c_addr[j+1] = spcl.c_addr[j]; 593*7c478bd9Sstevel@tonic-gate tpblkoff = 0; 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate /* LINTED (count - skip) will always fit into an int32_t */ 596*7c478bd9Sstevel@tonic-gate spcl.c_count = count - skip; 597*7c478bd9Sstevel@tonic-gate toslave(dospcl, ino); 598*7c478bd9Sstevel@tonic-gate bytecnt = MIN(bytes, bytecnt ? 599*7c478bd9Sstevel@tonic-gate bytecnt : (unsigned)(sblock->fs_bsize)); 600*7c478bd9Sstevel@tonic-gate j = 0; 601*7c478bd9Sstevel@tonic-gate while (j < count - skip) { 602*7c478bd9Sstevel@tonic-gate if (*blkp != 0) { 603*7c478bd9Sstevel@tonic-gate /* LINTED: fragoff fits into 32 bits */ 604*7c478bd9Sstevel@tonic-gate dmpblk(*blkp+(int32_t)fragoff, 605*7c478bd9Sstevel@tonic-gate /* LINTED: bytecnt fits into 32 bits */ 606*7c478bd9Sstevel@tonic-gate (size_t)bytecnt, byteoff); 607*7c478bd9Sstevel@tonic-gate } 608*7c478bd9Sstevel@tonic-gate blkp++; 609*7c478bd9Sstevel@tonic-gate bytes -= bytecnt; 610*7c478bd9Sstevel@tonic-gate /* LINTED: spurious complaint on sign-extending */ 611*7c478bd9Sstevel@tonic-gate j += d_howmany(bytecnt, (u_offset_t)tp_bsize); 612*7c478bd9Sstevel@tonic-gate bytecnt = MIN(bytes, (unsigned)(sblock->fs_bsize)); 613*7c478bd9Sstevel@tonic-gate byteoff = 0; 614*7c478bd9Sstevel@tonic-gate fragoff = 0; 615*7c478bd9Sstevel@tonic-gate } 616*7c478bd9Sstevel@tonic-gate spcl.c_type = TS_ADDR; 617*7c478bd9Sstevel@tonic-gate bytecnt = 0; 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate pos = 0; 620*7c478bd9Sstevel@tonic-gate } 621*7c478bd9Sstevel@tonic-gate 622*7c478bd9Sstevel@tonic-gate void 623*7c478bd9Sstevel@tonic-gate bitmap(map, typ) 624*7c478bd9Sstevel@tonic-gate uchar_t *map; 625*7c478bd9Sstevel@tonic-gate int typ; 626*7c478bd9Sstevel@tonic-gate { 627*7c478bd9Sstevel@tonic-gate int i; 628*7c478bd9Sstevel@tonic-gate u_offset_t count; 629*7c478bd9Sstevel@tonic-gate uchar_t *cp; 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate if (!newtape) 632*7c478bd9Sstevel@tonic-gate spcl.c_type = typ; 633*7c478bd9Sstevel@tonic-gate else 634*7c478bd9Sstevel@tonic-gate newtape = 0; 635*7c478bd9Sstevel@tonic-gate for (i = 0; i < TP_NINDIR; i++) 636*7c478bd9Sstevel@tonic-gate spcl.c_addr[i] = 1; 637*7c478bd9Sstevel@tonic-gate /* LINTED: spurious complaint on sign-extending */ 638*7c478bd9Sstevel@tonic-gate count = d_howmany(msiz * sizeof (map[0]), tp_bsize) - pos; 639*7c478bd9Sstevel@tonic-gate for (cp = &map[pos * tp_bsize]; count > 0; 640*7c478bd9Sstevel@tonic-gate count -= (u_offset_t)(unsigned)spcl.c_count) { 641*7c478bd9Sstevel@tonic-gate if (leftover) { 642*7c478bd9Sstevel@tonic-gate spcl.c_count = leftover; 643*7c478bd9Sstevel@tonic-gate leftover = 0; 644*7c478bd9Sstevel@tonic-gate } else { 645*7c478bd9Sstevel@tonic-gate /* LINTED value always less than INT32_MAX */ 646*7c478bd9Sstevel@tonic-gate spcl.c_count = count > TP_NINDIR ? TP_NINDIR : count; 647*7c478bd9Sstevel@tonic-gate } 648*7c478bd9Sstevel@tonic-gate spclrec(); 649*7c478bd9Sstevel@tonic-gate for (i = 0; i < spcl.c_count; i++, cp += tp_bsize) 650*7c478bd9Sstevel@tonic-gate taprec(cp, 0, tp_bsize); 651*7c478bd9Sstevel@tonic-gate spcl.c_type = TS_ADDR; 652*7c478bd9Sstevel@tonic-gate } 653*7c478bd9Sstevel@tonic-gate } 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate static void 656*7c478bd9Sstevel@tonic-gate dsrch(d, size, filesize) 657*7c478bd9Sstevel@tonic-gate daddr32_t d; 658*7c478bd9Sstevel@tonic-gate ulong_t size; /* block size */ 659*7c478bd9Sstevel@tonic-gate u_offset_t filesize; 660*7c478bd9Sstevel@tonic-gate { 661*7c478bd9Sstevel@tonic-gate struct direct *dp; 662*7c478bd9Sstevel@tonic-gate struct dinode *ip; 663*7c478bd9Sstevel@tonic-gate ulong_t loc; 664*7c478bd9Sstevel@tonic-gate char dblk[MAXBSIZE]; 665*7c478bd9Sstevel@tonic-gate 666*7c478bd9Sstevel@tonic-gate if (dadded || filesize == 0) 667*7c478bd9Sstevel@tonic-gate return; 668*7c478bd9Sstevel@tonic-gate if (filesize > (u_offset_t)size) 669*7c478bd9Sstevel@tonic-gate filesize = (u_offset_t)size; 670*7c478bd9Sstevel@tonic-gate if (sizeof (dblk) < roundup(filesize, DEV_BSIZE)) { 671*7c478bd9Sstevel@tonic-gate msg(gettext( 672*7c478bd9Sstevel@tonic-gate "Inconsistency detected: filesystem block size larger than valid maximum.\n")); 673*7c478bd9Sstevel@tonic-gate dumpabort(); 674*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 675*7c478bd9Sstevel@tonic-gate } 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate #ifdef lint 678*7c478bd9Sstevel@tonic-gate dblk[0] = '\0'; 679*7c478bd9Sstevel@tonic-gate #endif /* lint */ 680*7c478bd9Sstevel@tonic-gate 681*7c478bd9Sstevel@tonic-gate /* LINTED ufs disk addresses always fit into 32 bits */ 682*7c478bd9Sstevel@tonic-gate bread(fsbtodb(sblock, d), (uchar_t *)dblk, 683*7c478bd9Sstevel@tonic-gate /* LINTED from sizeof check above, roundup() <= max(size_t) */ 684*7c478bd9Sstevel@tonic-gate (size_t)(roundup(filesize, DEV_BSIZE))); 685*7c478bd9Sstevel@tonic-gate loc = 0; 686*7c478bd9Sstevel@tonic-gate while ((u_offset_t)loc < filesize) { 687*7c478bd9Sstevel@tonic-gate /*LINTED [dblk is char[], loc (dp->d_reclen) % 4 == 0]*/ 688*7c478bd9Sstevel@tonic-gate dp = (struct direct *)(dblk + loc); 689*7c478bd9Sstevel@tonic-gate if (dp->d_reclen == 0) { 690*7c478bd9Sstevel@tonic-gate (void) snprintf(msgbuf, sizeof (msgbuf), gettext( 691*7c478bd9Sstevel@tonic-gate "Warning - directory at inode `%lu' is corrupted\n"), 692*7c478bd9Sstevel@tonic-gate ino); 693*7c478bd9Sstevel@tonic-gate msg(msgbuf); 694*7c478bd9Sstevel@tonic-gate break; 695*7c478bd9Sstevel@tonic-gate } 696*7c478bd9Sstevel@tonic-gate loc += dp->d_reclen; 697*7c478bd9Sstevel@tonic-gate if (dp->d_ino == 0) 698*7c478bd9Sstevel@tonic-gate continue; 699*7c478bd9Sstevel@tonic-gate if (dp->d_name[0] == '.') { 700*7c478bd9Sstevel@tonic-gate if (dp->d_name[1] == '\0') { 701*7c478bd9Sstevel@tonic-gate if ((ino_t)(dp->d_ino) != ino) { 702*7c478bd9Sstevel@tonic-gate (void) snprintf(msgbuf, sizeof (msgbuf), 703*7c478bd9Sstevel@tonic-gate gettext( 704*7c478bd9Sstevel@tonic-gate "Warning - directory at inode `%lu' is corrupted:\n\ 705*7c478bd9Sstevel@tonic-gate \t\".\" points to inode `%lu' - run fsck\n"), 706*7c478bd9Sstevel@tonic-gate ino, dp->d_ino); 707*7c478bd9Sstevel@tonic-gate msg(msgbuf); 708*7c478bd9Sstevel@tonic-gate } 709*7c478bd9Sstevel@tonic-gate continue; 710*7c478bd9Sstevel@tonic-gate } 711*7c478bd9Sstevel@tonic-gate if (dp->d_name[1] == '.' && dp->d_name[2] == '\0') { 712*7c478bd9Sstevel@tonic-gate if (!BIT(dp->d_ino, dirmap) && 713*7c478bd9Sstevel@tonic-gate ((ip = getino(ino)) == NULL || 714*7c478bd9Sstevel@tonic-gate (ip->di_mode & IFMT) != IFATTRDIR)) { 715*7c478bd9Sstevel@tonic-gate (void) snprintf(msgbuf, sizeof (msgbuf), 716*7c478bd9Sstevel@tonic-gate gettext( 717*7c478bd9Sstevel@tonic-gate "Warning - directory at inode `%lu' is corrupted:\n\ 718*7c478bd9Sstevel@tonic-gate \t\"..\" points to non-directory inode `%lu' - run fsck\n"), 719*7c478bd9Sstevel@tonic-gate ino, dp->d_ino); 720*7c478bd9Sstevel@tonic-gate msg(msgbuf); 721*7c478bd9Sstevel@tonic-gate } 722*7c478bd9Sstevel@tonic-gate continue; 723*7c478bd9Sstevel@tonic-gate } 724*7c478bd9Sstevel@tonic-gate } 725*7c478bd9Sstevel@tonic-gate if (BIT(dp->d_ino, nodmap)) { 726*7c478bd9Sstevel@tonic-gate dadded++; 727*7c478bd9Sstevel@tonic-gate return; 728*7c478bd9Sstevel@tonic-gate } 729*7c478bd9Sstevel@tonic-gate if (BIT(dp->d_ino, dirmap)) 730*7c478bd9Sstevel@tonic-gate nsubdir++; 731*7c478bd9Sstevel@tonic-gate } 732*7c478bd9Sstevel@tonic-gate } 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate #define CACHESIZE 32 735*7c478bd9Sstevel@tonic-gate 736*7c478bd9Sstevel@tonic-gate struct dinode * 737*7c478bd9Sstevel@tonic-gate getino(ino) 738*7c478bd9Sstevel@tonic-gate ino_t ino; 739*7c478bd9Sstevel@tonic-gate { 740*7c478bd9Sstevel@tonic-gate static ino_t minino, maxino; 741*7c478bd9Sstevel@tonic-gate static struct dinode itab[MAXINOPB]; 742*7c478bd9Sstevel@tonic-gate static struct dinode icache[CACHESIZE]; 743*7c478bd9Sstevel@tonic-gate static ino_t icacheval[CACHESIZE], lasti = 0; 744*7c478bd9Sstevel@tonic-gate static int cacheoff = 0; 745*7c478bd9Sstevel@tonic-gate int i; 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate if (ino >= minino && ino < maxino) { 748*7c478bd9Sstevel@tonic-gate lasti = ino; 749*7c478bd9Sstevel@tonic-gate return (&itab[ino - minino]); 750*7c478bd9Sstevel@tonic-gate } 751*7c478bd9Sstevel@tonic-gate 752*7c478bd9Sstevel@tonic-gate /* before we do major i/o, check for a secondary cache hit */ 753*7c478bd9Sstevel@tonic-gate for (i = 0; i < CACHESIZE; i++) 754*7c478bd9Sstevel@tonic-gate if (icacheval[i] == ino) 755*7c478bd9Sstevel@tonic-gate return (icache + i); 756*7c478bd9Sstevel@tonic-gate 757*7c478bd9Sstevel@tonic-gate /* we need to do major i/o. throw the last inode retrieved into */ 758*7c478bd9Sstevel@tonic-gate /* the cache. note: this copies garbage the first time it is */ 759*7c478bd9Sstevel@tonic-gate /* used, but no harm done. */ 760*7c478bd9Sstevel@tonic-gate icacheval[cacheoff] = lasti; 761*7c478bd9Sstevel@tonic-gate bcopy(itab + (lasti - minino), icache + cacheoff, sizeof (itab[0])); 762*7c478bd9Sstevel@tonic-gate lasti = ino; 763*7c478bd9Sstevel@tonic-gate if (++cacheoff >= CACHESIZE) 764*7c478bd9Sstevel@tonic-gate cacheoff = 0; 765*7c478bd9Sstevel@tonic-gate 766*7c478bd9Sstevel@tonic-gate #define INOPERDB (DEV_BSIZE / sizeof (struct dinode)) 767*7c478bd9Sstevel@tonic-gate minino = ino &~ (INOPERDB - 1); 768*7c478bd9Sstevel@tonic-gate maxino = ((itog(sblock, ino) + 1) * (unsigned)(sblock->fs_ipg)); 769*7c478bd9Sstevel@tonic-gate if (maxino > minino + MAXINOPB) 770*7c478bd9Sstevel@tonic-gate maxino = minino + MAXINOPB; 771*7c478bd9Sstevel@tonic-gate bread( 772*7c478bd9Sstevel@tonic-gate /* LINTED: can't make up for broken system macros here */ 773*7c478bd9Sstevel@tonic-gate (fsbtodb(sblock, itod(sblock, ino)) + itoo(sblock, ino) / INOPERDB), 774*7c478bd9Sstevel@tonic-gate /* LINTED: (max - min) * size fits into a size_t */ 775*7c478bd9Sstevel@tonic-gate (uchar_t *)itab, (size_t)((maxino - minino) * sizeof (*itab))); 776*7c478bd9Sstevel@tonic-gate return (&itab[ino - minino]); 777*7c478bd9Sstevel@tonic-gate } 778*7c478bd9Sstevel@tonic-gate 779*7c478bd9Sstevel@tonic-gate #define BREADEMAX 32 780*7c478bd9Sstevel@tonic-gate 781*7c478bd9Sstevel@tonic-gate #ifdef NO__LONGLONG__ 782*7c478bd9Sstevel@tonic-gate #define DEV_LSEEK(fd, offset, whence) \ 783*7c478bd9Sstevel@tonic-gate lseek((fd), (((off_t)(offset))*DEV_BSIZE), (whence)) 784*7c478bd9Sstevel@tonic-gate #else 785*7c478bd9Sstevel@tonic-gate #define DEV_LSEEK(fd, offset, whence) \ 786*7c478bd9Sstevel@tonic-gate llseek((fd), (((offset_t)(((unsigned)offset)))*DEV_BSIZE), (whence)) 787*7c478bd9Sstevel@tonic-gate #endif 788*7c478bd9Sstevel@tonic-gate 789*7c478bd9Sstevel@tonic-gate #define BREAD_FAIL(buf, size) { \ 790*7c478bd9Sstevel@tonic-gate breaderrors += 1; \ 791*7c478bd9Sstevel@tonic-gate bzero(buf, (size_t)size); \ 792*7c478bd9Sstevel@tonic-gate } 793*7c478bd9Sstevel@tonic-gate 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate 796*7c478bd9Sstevel@tonic-gate void 797*7c478bd9Sstevel@tonic-gate bread(da, ba, cnt) 798*7c478bd9Sstevel@tonic-gate diskaddr_t da; 799*7c478bd9Sstevel@tonic-gate uchar_t *ba; 800*7c478bd9Sstevel@tonic-gate size_t cnt; 801*7c478bd9Sstevel@tonic-gate { 802*7c478bd9Sstevel@tonic-gate caddr_t maddr; 803*7c478bd9Sstevel@tonic-gate uchar_t *dest; 804*7c478bd9Sstevel@tonic-gate int saverr; 805*7c478bd9Sstevel@tonic-gate int n; 806*7c478bd9Sstevel@tonic-gate size_t len; 807*7c478bd9Sstevel@tonic-gate off64_t filoff; 808*7c478bd9Sstevel@tonic-gate off64_t mapoff; 809*7c478bd9Sstevel@tonic-gate off64_t displacement; 810*7c478bd9Sstevel@tonic-gate 811*7c478bd9Sstevel@tonic-gate static size_t pagesize = 0; 812*7c478bd9Sstevel@tonic-gate static int breaderrors = 0; 813*7c478bd9Sstevel@tonic-gate 814*7c478bd9Sstevel@tonic-gate /* mechanics for caching small bread requests. these are */ 815*7c478bd9Sstevel@tonic-gate /* often small ACLs that are used over and over. */ 816*7c478bd9Sstevel@tonic-gate static uchar_t bcache[DEV_BSIZE * CACHESIZE]; 817*7c478bd9Sstevel@tonic-gate static diskaddr_t bcacheval[CACHESIZE]; 818*7c478bd9Sstevel@tonic-gate static int cacheoff = 0; 819*7c478bd9Sstevel@tonic-gate int i; 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate if ((cnt >= DEV_BSIZE) && (mapfd != -1)) { 822*7c478bd9Sstevel@tonic-gate if (pagesize == 0) 823*7c478bd9Sstevel@tonic-gate pagesize = getpagesize(); 824*7c478bd9Sstevel@tonic-gate /* 825*7c478bd9Sstevel@tonic-gate * We depend on mmap(2)'s guarantee that mapping a 826*7c478bd9Sstevel@tonic-gate * partial page will cause the remainder of the page 827*7c478bd9Sstevel@tonic-gate * to be zero-filled. 828*7c478bd9Sstevel@tonic-gate */ 829*7c478bd9Sstevel@tonic-gate filoff = ((off64_t)da) * DEV_BSIZE; 830*7c478bd9Sstevel@tonic-gate displacement = filoff & (pagesize - 1); 831*7c478bd9Sstevel@tonic-gate mapoff = filoff - displacement; 832*7c478bd9Sstevel@tonic-gate /* LINTED offset will fit into 32 bits */ 833*7c478bd9Sstevel@tonic-gate len = (size_t)roundup(cnt + (filoff - mapoff), pagesize); 834*7c478bd9Sstevel@tonic-gate maddr = mmap64(NULL, len, PROT_READ, MAP_SHARED, mapfd, mapoff); 835*7c478bd9Sstevel@tonic-gate if (maddr != MAP_FAILED) { 836*7c478bd9Sstevel@tonic-gate (void) memcpy(ba, maddr + displacement, cnt); 837*7c478bd9Sstevel@tonic-gate (void) munmap(maddr, len); 838*7c478bd9Sstevel@tonic-gate return; 839*7c478bd9Sstevel@tonic-gate } 840*7c478bd9Sstevel@tonic-gate } 841*7c478bd9Sstevel@tonic-gate 842*7c478bd9Sstevel@tonic-gate if (DEV_LSEEK(fi, da, L_SET) < 0) { 843*7c478bd9Sstevel@tonic-gate saverr = errno; 844*7c478bd9Sstevel@tonic-gate msg(gettext("bread: dev_seek error: %s\n"), strerror(saverr)); 845*7c478bd9Sstevel@tonic-gate /* Don't know where we are, return the least-harmful data */ 846*7c478bd9Sstevel@tonic-gate BREAD_FAIL(ba, cnt); 847*7c478bd9Sstevel@tonic-gate return; 848*7c478bd9Sstevel@tonic-gate } 849*7c478bd9Sstevel@tonic-gate 850*7c478bd9Sstevel@tonic-gate if (read(fi, ba, (size_t)cnt) == (size_t)cnt) 851*7c478bd9Sstevel@tonic-gate return; 852*7c478bd9Sstevel@tonic-gate 853*7c478bd9Sstevel@tonic-gate while (cnt != 0) { 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate if (da >= fsbtodb(sblock, sblock->fs_size)) { 856*7c478bd9Sstevel@tonic-gate msg(gettext( 857*7c478bd9Sstevel@tonic-gate "Warning - block %llu is beyond the end of `%s'\n"), 858*7c478bd9Sstevel@tonic-gate da, disk); 859*7c478bd9Sstevel@tonic-gate BREAD_FAIL(ba, cnt); 860*7c478bd9Sstevel@tonic-gate break; 861*7c478bd9Sstevel@tonic-gate } 862*7c478bd9Sstevel@tonic-gate 863*7c478bd9Sstevel@tonic-gate if (DEV_LSEEK(fi, da, L_SET) < 0) { 864*7c478bd9Sstevel@tonic-gate msg(gettext("%s: %s error\n"), "bread", "DEV_LSEEK2"); 865*7c478bd9Sstevel@tonic-gate BREAD_FAIL(ba, cnt); 866*7c478bd9Sstevel@tonic-gate break; 867*7c478bd9Sstevel@tonic-gate } 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate if (cnt < DEV_BSIZE) { 870*7c478bd9Sstevel@tonic-gate /* small read. check for cache hit. */ 871*7c478bd9Sstevel@tonic-gate for (i = 0; i < CACHESIZE; i++) 872*7c478bd9Sstevel@tonic-gate if (bcacheval[i] == da) { 873*7c478bd9Sstevel@tonic-gate bcopy(bcache + (i * DEV_BSIZE), 874*7c478bd9Sstevel@tonic-gate ba, cnt); 875*7c478bd9Sstevel@tonic-gate return; 876*7c478bd9Sstevel@tonic-gate } 877*7c478bd9Sstevel@tonic-gate 878*7c478bd9Sstevel@tonic-gate /* no cache hit; throw this one into the cache... */ 879*7c478bd9Sstevel@tonic-gate len = cnt; 880*7c478bd9Sstevel@tonic-gate dest = bcache + (cacheoff * DEV_BSIZE); 881*7c478bd9Sstevel@tonic-gate bcacheval[cacheoff] = da; 882*7c478bd9Sstevel@tonic-gate if (++cacheoff >= CACHESIZE) 883*7c478bd9Sstevel@tonic-gate cacheoff = 0; 884*7c478bd9Sstevel@tonic-gate } else { 885*7c478bd9Sstevel@tonic-gate len = DEV_BSIZE; 886*7c478bd9Sstevel@tonic-gate dest = ba; 887*7c478bd9Sstevel@tonic-gate } 888*7c478bd9Sstevel@tonic-gate 889*7c478bd9Sstevel@tonic-gate n = read(fi, dest, DEV_BSIZE); 890*7c478bd9Sstevel@tonic-gate if (n != DEV_BSIZE) { 891*7c478bd9Sstevel@tonic-gate n = MAX(n, 0); 892*7c478bd9Sstevel@tonic-gate bzero(dest+n, DEV_BSIZE-n); 893*7c478bd9Sstevel@tonic-gate breaderrors += 1; 894*7c478bd9Sstevel@tonic-gate msg(gettext( 895*7c478bd9Sstevel@tonic-gate "Warning - cannot read sector %llu of `%s'\n"), 896*7c478bd9Sstevel@tonic-gate da, disk); 897*7c478bd9Sstevel@tonic-gate } 898*7c478bd9Sstevel@tonic-gate if (dest != ba) 899*7c478bd9Sstevel@tonic-gate bcopy(dest, ba, len); 900*7c478bd9Sstevel@tonic-gate 901*7c478bd9Sstevel@tonic-gate da++; 902*7c478bd9Sstevel@tonic-gate /* LINTED character pointers aren't signed */ 903*7c478bd9Sstevel@tonic-gate ba += len; 904*7c478bd9Sstevel@tonic-gate cnt -= len; 905*7c478bd9Sstevel@tonic-gate } 906*7c478bd9Sstevel@tonic-gate 907*7c478bd9Sstevel@tonic-gate if (breaderrors > BREADEMAX) { 908*7c478bd9Sstevel@tonic-gate msg(gettext( 909*7c478bd9Sstevel@tonic-gate "More than %d block read errors from dump device `%s'\n"), 910*7c478bd9Sstevel@tonic-gate BREADEMAX, disk); 911*7c478bd9Sstevel@tonic-gate dumpailing(); 912*7c478bd9Sstevel@tonic-gate breaderrors = 0; 913*7c478bd9Sstevel@tonic-gate } 914*7c478bd9Sstevel@tonic-gate } 915