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