1: /* 2: * Copyright (c) 1980 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifndef lint 8: static char sccsid[] = "@(#)dumptraverse.c 5.3 (Berkeley) 1/9/86"; 9: #endif not lint 10: 11: #include "dump.h" 12: 13: pass(fn, map) 14: register int (*fn)(); 15: register char *map; 16: { 17: register int bits; 18: ino_t maxino; 19: 20: maxino = sblock->fs_ipg * sblock->fs_ncg - 1; 21: for (ino = 0; ino < maxino; ) { 22: if ((ino % NBBY) == 0) { 23: bits = ~0; 24: if (map != NULL) 25: bits = *map++; 26: } 27: ino++; 28: if (bits & 1) 29: (*fn)(getino(ino)); 30: bits >>= 1; 31: } 32: } 33: 34: mark(ip) 35: struct dinode *ip; 36: { 37: register int f; 38: extern int anydskipped; 39: 40: f = ip->di_mode & IFMT; 41: if (f == 0) 42: return; 43: BIS(ino, clrmap); 44: if (f == IFDIR) 45: BIS(ino, dirmap); 46: if ((ip->di_mtime >= spcl.c_ddate || ip->di_ctime >= spcl.c_ddate) && 47: !BIT(ino, nodmap)) { 48: BIS(ino, nodmap); 49: if (f != IFREG && f != IFDIR && f != IFLNK) { 50: esize += 1; 51: return; 52: } 53: est(ip); 54: } else if (f == IFDIR) 55: anydskipped = 1; 56: } 57: 58: add(ip) 59: register struct dinode *ip; 60: { 61: register int i; 62: long filesize; 63: 64: if(BIT(ino, nodmap)) 65: return; 66: nsubdir = 0; 67: dadded = 0; 68: filesize = ip->di_size; 69: for (i = 0; i < NDADDR; i++) { 70: if (ip->di_db[i] != 0) 71: dsrch(ip->di_db[i], dblksize(sblock, ip, i), filesize); 72: filesize -= sblock->fs_bsize; 73: } 74: for (i = 0; i < NIADDR; i++) { 75: if (ip->di_ib[i] != 0) 76: indir(ip->di_ib[i], i, &filesize); 77: } 78: if(dadded) { 79: nadded++; 80: if (!BIT(ino, nodmap)) { 81: BIS(ino, nodmap); 82: est(ip); 83: } 84: } 85: if(nsubdir == 0) 86: if(!BIT(ino, nodmap)) 87: BIC(ino, dirmap); 88: } 89: 90: indir(d, n, filesize) 91: daddr_t d; 92: int n, *filesize; 93: { 94: register i; 95: daddr_t idblk[MAXNINDIR]; 96: 97: bread(fsbtodb(sblock, d), (char *)idblk, sblock->fs_bsize); 98: if(n <= 0) { 99: for(i=0; i < NINDIR(sblock); i++) { 100: d = idblk[i]; 101: if(d != 0) 102: dsrch(d, sblock->fs_bsize, *filesize); 103: *filesize -= sblock->fs_bsize; 104: } 105: } else { 106: n--; 107: for(i=0; i < NINDIR(sblock); i++) { 108: d = idblk[i]; 109: if(d != 0) 110: indir(d, n, filesize); 111: } 112: } 113: } 114: 115: dirdump(ip) 116: struct dinode *ip; 117: { 118: /* watchout for dir inodes deleted and maybe reallocated */ 119: if ((ip->di_mode & IFMT) != IFDIR) 120: return; 121: dump(ip); 122: } 123: 124: dump(ip) 125: struct dinode *ip; 126: { 127: register int i; 128: long size; 129: 130: if(newtape) { 131: newtape = 0; 132: bitmap(nodmap, TS_BITS); 133: } 134: BIC(ino, nodmap); 135: spcl.c_dinode = *ip; 136: spcl.c_type = TS_INODE; 137: spcl.c_count = 0; 138: i = ip->di_mode & IFMT; 139: if (i == 0) /* free inode */ 140: return; 141: if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) { 142: spclrec(); 143: return; 144: } 145: if (ip->di_size > NDADDR * sblock->fs_bsize) 146: i = NDADDR * sblock->fs_frag; 147: else 148: i = howmany(ip->di_size, sblock->fs_fsize); 149: blksout(&ip->di_db[0], i); 150: size = ip->di_size - NDADDR * sblock->fs_bsize; 151: if (size <= 0) 152: return; 153: for (i = 0; i < NIADDR; i++) { 154: dmpindir(ip->di_ib[i], i, &size); 155: if (size <= 0) 156: return; 157: } 158: } 159: 160: dmpindir(blk, lvl, size) 161: daddr_t blk; 162: int lvl; 163: long *size; 164: { 165: int i, cnt; 166: daddr_t idblk[MAXNINDIR]; 167: 168: if (blk != 0) 169: bread(fsbtodb(sblock, blk), (char *)idblk, sblock->fs_bsize); 170: else 171: bzero(idblk, sblock->fs_bsize); 172: if (lvl <= 0) { 173: if (*size < NINDIR(sblock) * sblock->fs_bsize) 174: cnt = howmany(*size, sblock->fs_fsize); 175: else 176: cnt = NINDIR(sblock) * sblock->fs_frag; 177: *size -= NINDIR(sblock) * sblock->fs_bsize; 178: blksout(&idblk[0], cnt); 179: return; 180: } 181: lvl--; 182: for (i = 0; i < NINDIR(sblock); i++) { 183: dmpindir(idblk[i], lvl, size); 184: if (*size <= 0) 185: return; 186: } 187: } 188: 189: blksout(blkp, frags) 190: daddr_t *blkp; 191: int frags; 192: { 193: int i, j, count, blks, tbperdb; 194: 195: blks = howmany(frags * sblock->fs_fsize, TP_BSIZE); 196: tbperdb = sblock->fs_bsize / TP_BSIZE; 197: for (i = 0; i < blks; i += TP_NINDIR) { 198: if (i + TP_NINDIR > blks) 199: count = blks; 200: else 201: count = i + TP_NINDIR; 202: for (j = i; j < count; j++) 203: if (blkp[j / tbperdb] != 0) 204: spcl.c_addr[j - i] = 1; 205: else 206: spcl.c_addr[j - i] = 0; 207: spcl.c_count = count - i; 208: spclrec(); 209: for (j = i; j < count; j += tbperdb) 210: if (blkp[j / tbperdb] != 0) 211: if (j + tbperdb <= count) 212: dmpblk(blkp[j / tbperdb], 213: sblock->fs_bsize); 214: else 215: dmpblk(blkp[j / tbperdb], 216: (count - j) * TP_BSIZE); 217: spcl.c_type = TS_ADDR; 218: } 219: } 220: 221: bitmap(map, typ) 222: char *map; 223: { 224: register i; 225: char *cp; 226: 227: spcl.c_type = typ; 228: spcl.c_count = howmany(msiz * sizeof(map[0]), TP_BSIZE); 229: spclrec(); 230: for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE) 231: taprec(cp); 232: } 233: 234: spclrec() 235: { 236: register int s, i, *ip; 237: 238: spcl.c_inumber = ino; 239: spcl.c_magic = NFS_MAGIC; 240: spcl.c_checksum = 0; 241: ip = (int *)&spcl; 242: s = 0; 243: i = sizeof(union u_spcl) / (4*sizeof(int)); 244: while (--i >= 0) { 245: s += *ip++; s += *ip++; 246: s += *ip++; s += *ip++; 247: } 248: spcl.c_checksum = CHECKSUM - s; 249: taprec((char *)&spcl); 250: } 251: 252: dsrch(d, size, filesize) 253: daddr_t d; 254: int size, filesize; 255: { 256: register struct direct *dp; 257: long loc; 258: char dblk[MAXBSIZE]; 259: 260: if(dadded) 261: return; 262: if (filesize > size) 263: filesize = size; 264: bread(fsbtodb(sblock, d), dblk, filesize); 265: for (loc = 0; loc < filesize; ) { 266: dp = (struct direct *)(dblk + loc); 267: if (dp->d_reclen == 0) { 268: msg("corrupted directory, inumber %d\n", ino); 269: break; 270: } 271: loc += dp->d_reclen; 272: if(dp->d_ino == 0) 273: continue; 274: if(dp->d_name[0] == '.') { 275: if(dp->d_name[1] == '\0') 276: continue; 277: if(dp->d_name[1] == '.' && dp->d_name[2] == '\0') 278: continue; 279: } 280: if(BIT(dp->d_ino, nodmap)) { 281: dadded++; 282: return; 283: } 284: if(BIT(dp->d_ino, dirmap)) 285: nsubdir++; 286: } 287: } 288: 289: struct dinode * 290: getino(ino) 291: daddr_t ino; 292: { 293: static daddr_t minino, maxino; 294: static struct dinode itab[MAXINOPB]; 295: 296: if (ino >= minino && ino < maxino) { 297: return (&itab[ino - minino]); 298: } 299: bread(fsbtodb(sblock, itod(sblock, ino)), itab, sblock->fs_bsize); 300: minino = ino - (ino % INOPB(sblock)); 301: maxino = minino + INOPB(sblock); 302: return (&itab[ino - minino]); 303: } 304: 305: int breaderrors = 0; 306: #define BREADEMAX 32 307: 308: bread(da, ba, cnt) 309: daddr_t da; 310: char *ba; 311: int cnt; 312: { 313: int n; 314: 315: loop: 316: if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0){ 317: msg("bread: lseek fails\n"); 318: } 319: n = read(fi, ba, cnt); 320: if (n == cnt) 321: return; 322: if (da + (cnt / DEV_BSIZE) > fsbtodb(sblock, sblock->fs_size)) { 323: /* 324: * Trying to read the final fragment. 325: * 326: * NB - dump only works in TP_BSIZE blocks, hence 327: * rounds DEV_BSIZE fragments up to TP_BSIZE pieces. 328: * It should be smarter about not actually trying to 329: * read more than it can get, but for the time being 330: * we punt and scale back the read only when it gets 331: * us into trouble. (mkm 9/25/83) 332: */ 333: cnt -= DEV_BSIZE; 334: goto loop; 335: } 336: msg("(This should not happen)bread from %s [block %d]: count=%d, got=%d\n", 337: disk, da, cnt, n); 338: if (++breaderrors > BREADEMAX){ 339: msg("More than %d block read errors from %d\n", 340: BREADEMAX, disk); 341: broadcast("DUMP IS AILING!\n"); 342: msg("This is an unrecoverable error.\n"); 343: if (!query("Do you want to attempt to continue?")){ 344: dumpabort(); 345: /*NOTREACHED*/ 346: } else 347: breaderrors = 0; 348: } 349: }