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