1: #if !defined(lint) && defined(DOSCCS) 2: static char *sccsid = "@(#)dumptraverse.c 1.2 (2.11BSD GTE) 12/6/94"; 3: #endif 4: 5: #include "dump.h" 6: 7: struct fs sblock; /* disk block */ 8: struct dinode itab[INOPB * NI]; 9: 10: pass(fn, map) 11: int (*fn)(); 12: short *map; 13: { 14: register i, j; 15: int bits; 16: ino_t mino; 17: daddr_t d; 18: 19: sync(); 20: bread((daddr_t)1, (char *)&sblock, sizeof(sblock)); 21: mino = (sblock.fs_isize-2) * INOPB; 22: ino = 0; 23: for(i=2;; i+=NI) { 24: if(ino >= mino) 25: break; 26: d = (unsigned)i; 27: for(j=0; j<INOPB*NI; j++) { 28: if(ino >= mino) 29: break; 30: if((ino % MLEN) == 0) { 31: bits = ~0; 32: if(map != NULL) 33: bits = *map++; 34: } 35: ino++; 36: if(bits & 1) { 37: if(d != 0) { 38: bread(d, (char *)itab, sizeof(itab)); 39: d = 0; 40: } 41: (*fn)(&itab[j]); 42: } 43: bits >>= 1; 44: } 45: } 46: } 47: 48: icat(ip, fn1, fn2) 49: struct dinode *ip; 50: int (*fn1)(), (*fn2)(); 51: { 52: register i; 53: 54: (*fn2)(ip->di_addr, NADDR-3); 55: for(i=0; i<NADDR; i++) { 56: if(ip->di_addr[i] != 0) { 57: if(i < NADDR-3) 58: (*fn1)(ip->di_addr[i]); else 59: indir(ip->di_addr[i], fn1, fn2, i-(NADDR-3)); 60: } 61: } 62: } 63: 64: indir(d, fn1, fn2, n) 65: daddr_t d; 66: int (*fn1)(), (*fn2)(); 67: { 68: register i; 69: daddr_t idblk[NINDIR]; 70: 71: bread(d, (char *)idblk, sizeof(idblk)); 72: if(n <= 0) { 73: spcl.c_type = TS_ADDR; 74: (*fn2)(idblk, NINDIR); 75: for(i=0; i<NINDIR; i++) { 76: d = idblk[i]; 77: if(d != 0) 78: (*fn1)(d); 79: } 80: } else { 81: n--; 82: for(i=0; i<NINDIR; i++) { 83: d = idblk[i]; 84: if(d != 0) 85: indir(d, fn1, fn2, n); 86: } 87: } 88: } 89: 90: #define CHANGEDSINCE(dp,t) ((dp)->di_mtime >= (t) || (dp)->di_ctime >= (t)) 91: #define WANTTODUMP(dp) (CHANGEDSINCE(dp,spcl.c_ddate) && \ 92: (nonodump || (dp->di_flags & UF_NODUMP) != UF_NODUMP)) 93: 94: mark(ip) 95: register struct dinode *ip; 96: { 97: register f; 98: 99: f = ip->di_mode & IFMT; 100: if(f == 0) 101: return; 102: BIS(ino, clrmap); 103: if(f == IFDIR) 104: BIS(ino, dirmap); 105: if (WANTTODUMP(ip)) { 106: BIS(ino, nodmap); 107: if (f != IFREG && f != IFDIR && f != IFLNK){ 108: esize++; 109: return; 110: } 111: est(ip); 112: } 113: } 114: 115: add(ip) 116: struct dinode *ip; 117: { 118: 119: if(BIT(ino, nodmap)) 120: return; 121: nsubdir = 0; 122: dadded = 0; 123: icat(ip, dsrch, nullf); 124: if(dadded) { 125: BIS(ino, nodmap); 126: est(ip); 127: nadded++; 128: } 129: if(nsubdir == 0) 130: if(!BIT(ino, nodmap)) 131: BIC(ino, dirmap); 132: } 133: 134: dump(ip) 135: struct dinode *ip; 136: { 137: register i; 138: 139: if(newtape) { 140: newtape = 0; 141: bitmap(nodmap, TS_BITS); 142: } 143: BIC(ino, nodmap); 144: spcl.c_dinode = *ip; 145: spcl.c_type = TS_INODE; 146: spcl.c_count = 0; 147: i = ip->di_mode & IFMT; 148: if(i != IFDIR && i != IFREG && i != IFLNK) { 149: spclrec(); 150: return; 151: } 152: icat(ip, tapsrec, dmpspc); 153: } 154: 155: dmpspc(dp, n) 156: daddr_t *dp; 157: { 158: register i, t; 159: 160: spcl.c_count = n; 161: for(i=0; i<n; i++) { 162: t = 0; 163: if(dp[i] != 0) 164: t++; 165: spcl.c_addr[i] = t; 166: } 167: spclrec(); 168: } 169: 170: bitmap(map, typ) 171: short *map; 172: { 173: register i, n; 174: char *cp; 175: 176: n = -1; 177: for(i=0; i<MSIZ; i++) 178: if(map[i]) 179: n = i; 180: if(n < 0) 181: return; 182: spcl.c_type = typ; 183: spcl.c_count = (n*sizeof(map[0]) + DEV_BSIZE)/DEV_BSIZE; 184: spclrec(); 185: cp = (char *)map; 186: for(i=0; i<spcl.c_count; i++) { 187: taprec(cp); 188: cp += DEV_BSIZE; 189: } 190: } 191: 192: spclrec() 193: { 194: register i, *ip, s; 195: 196: spcl.c_inumber = ino; 197: spcl.c_magic = NFS_MAGIC; 198: spcl.c_checksum = 0; 199: ip = (int *)&spcl; 200: s = 0; 201: for(i=0; i<DEV_BSIZE/sizeof(*ip); i++) 202: s += *ip++; 203: spcl.c_checksum = CHECKSUM - s; 204: taprec((char *)&spcl); 205: } 206: 207: dsrch(d) 208: daddr_t d; 209: { 210: register struct direct *dp; 211: register int i; 212: char dbuf[DEV_BSIZE]; 213: 214: if(dadded) 215: return; 216: bread(d, dbuf, DEV_BSIZE); 217: for (i = 0; i < DEV_BSIZE; ) { 218: dp = (struct direct *)(dbuf + i); 219: if (dp->d_reclen == 0) { 220: /* 221: * following hack is for directories which, although occupying a full fs block 222: * do not have the second DIRBLKSIZ section initialized to an empty dir blk. 223: */ 224: if (i != DIRBLKSIZ) /* XXX */ 225: fprintf(stderr,"corrupted directory, inumber %u\n",ino); 226: break; 227: } 228: i += dp->d_reclen; 229: if (dp->d_ino == 0) 230: continue; 231: if (dp->d_name[0] == '.') { 232: if (dp->d_name[1] == '\0') 233: continue; 234: if (dp->d_name[1] == '.' && dp->d_name[2] == '\0') 235: continue; 236: } 237: if(BIT(dp->d_ino, nodmap)) { 238: dadded++; 239: return; 240: } 241: if(BIT(dp->d_ino, dirmap)) 242: nsubdir++; 243: } 244: } 245: 246: nullf() 247: { 248: } 249: 250: int breaderrors = 0; 251: #define BREADEMAX 32 252: 253: bread(da, ba, c) 254: daddr_t da; 255: char *ba; 256: unsigned c; 257: { 258: register n; 259: register unsigned regc; 260: 261: if (lseek(fi, (off_t)da * DEV_BSIZE, 0) < 0) 262: msg("bread: lseek fails\n"); 263: regc = c; /* put c someplace safe; it gets clobbered */ 264: n = read(fi, ba, c); 265: if (n == -1 || ((unsigned)n) != c || regc != c){ 266: msg("(This should not happen)bread from %s [block %ld]: c=0x%x, regc=0x%x, &c=0x%x, n=0x%x\n", 267: disk, da, c, regc, &c, n); 268: if (++breaderrors > BREADEMAX){ 269: msg("More than %d block read errors from %d\n", 270: BREADEMAX, disk); 271: broadcast("DUMP IS AILING!\n"); 272: msg("This is an unrecoverable error.\n"); 273: if (!query("Do you want to attempt to continue?")){ 274: dumpabort(); 275: /*NOTREACHED*/ 276: } else 277: breaderrors = 0; 278: } 279: } 280: }