1*15095Smckusick static char *sccsid = "@(#)traverse.c 1.15 (Berkeley) 09/25/83"; 25329Smckusic 31426Sroot #include "dump.h" 41426Sroot 51426Sroot pass(fn, map) 64702Smckusic int (*fn)(); 75329Smckusic char *map; 81426Sroot { 94702Smckusic struct dinode *dp; 101426Sroot int bits; 114702Smckusic ino_t maxino; 121426Sroot 135329Smckusic maxino = sblock->fs_ipg * sblock->fs_ncg - 1; 144702Smckusic for (ino = 0; ino < maxino; ) { 155329Smckusic if((ino % NBBY) == 0) { 164702Smckusic bits = ~0; 174702Smckusic if(map != NULL) 184702Smckusic bits = *map++; 191426Sroot } 204702Smckusic ino++; 214702Smckusic if(bits & 1) { 224702Smckusic dp = getino(ino); 234702Smckusic (*fn)(dp); 244702Smckusic } 254702Smckusic bits >>= 1; 261426Sroot } 271426Sroot } 281426Sroot 291426Sroot mark(ip) 304777Smckusic struct dinode *ip; 311426Sroot { 321426Sroot register f; 331426Sroot 341426Sroot f = ip->di_mode & IFMT; 351426Sroot if(f == 0) 361426Sroot return; 371426Sroot BIS(ino, clrmap); 381426Sroot if(f == IFDIR) 391426Sroot BIS(ino, dirmap); 405329Smckusic if ((ip->di_mtime >= spcl.c_ddate || ip->di_ctime >= spcl.c_ddate) && 415329Smckusic !BIT(ino, nodmap)) { 421426Sroot BIS(ino, nodmap); 436288Smckusick if (f != IFREG && f != IFDIR && f != IFLNK) { 441426Sroot esize += 1; 451426Sroot return; 461426Sroot } 471426Sroot est(ip); 481426Sroot } 491426Sroot } 501426Sroot 511426Sroot add(ip) 525329Smckusic register struct dinode *ip; 531426Sroot { 545329Smckusic register int i; 5514928Smckusick long filesize; 561426Sroot 571426Sroot if(BIT(ino, nodmap)) 581426Sroot return; 591426Sroot nsubdir = 0; 601426Sroot dadded = 0; 6114928Smckusick filesize = ip->di_size; 625329Smckusic for (i = 0; i < NDADDR; i++) { 635329Smckusic if (ip->di_db[i] != 0) 6414928Smckusick dsrch(ip->di_db[i], dblksize(sblock, ip, i), filesize); 6514928Smckusick filesize -= sblock->fs_bsize; 665329Smckusic } 675329Smckusic for (i = 0; i < NIADDR; i++) { 685329Smckusic if (ip->di_ib[i] != 0) 6914928Smckusick indir(ip->di_ib[i], i, &filesize); 705329Smckusic } 711426Sroot if(dadded) { 721426Sroot nadded++; 735329Smckusic if (!BIT(ino, nodmap)) { 745329Smckusic BIS(ino, nodmap); 755329Smckusic est(ip); 765329Smckusic } 771426Sroot } 781426Sroot if(nsubdir == 0) 791426Sroot if(!BIT(ino, nodmap)) 801426Sroot BIC(ino, dirmap); 811426Sroot } 821426Sroot 8314928Smckusick indir(d, n, filesize) 845329Smckusic daddr_t d; 8514928Smckusick int n, *filesize; 865329Smckusic { 875329Smckusic register i; 885329Smckusic daddr_t idblk[MAXNINDIR]; 895329Smckusic 905329Smckusic bread(fsbtodb(sblock, d), (char *)idblk, sblock->fs_bsize); 915329Smckusic if(n <= 0) { 925329Smckusic for(i=0; i < NINDIR(sblock); i++) { 935329Smckusic d = idblk[i]; 945329Smckusic if(d != 0) 9514928Smckusick dsrch(d, sblock->fs_bsize, *filesize); 9614928Smckusick *filesize -= sblock->fs_bsize; 975329Smckusic } 985329Smckusic } else { 995329Smckusic n--; 1005329Smckusic for(i=0; i < NINDIR(sblock); i++) { 1015329Smckusic d = idblk[i]; 1025329Smckusic if(d != 0) 10314928Smckusick indir(d, n, filesize); 1045329Smckusic } 1055329Smckusic } 1065329Smckusic } 1075329Smckusic 1081426Sroot dump(ip) 1094777Smckusic struct dinode *ip; 1101426Sroot { 1114777Smckusic register int i; 1124777Smckusic long size; 1131426Sroot 1141426Sroot if(newtape) { 1151426Sroot newtape = 0; 1161426Sroot bitmap(nodmap, TS_BITS); 1171426Sroot } 1181426Sroot BIC(ino, nodmap); 1191426Sroot spcl.c_dinode = *ip; 1201426Sroot spcl.c_type = TS_INODE; 1211426Sroot spcl.c_count = 0; 1221426Sroot i = ip->di_mode & IFMT; 1236288Smckusick if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) { 1241426Sroot spclrec(); 1251426Sroot return; 1261426Sroot } 1275329Smckusic if (ip->di_size > NDADDR * sblock->fs_bsize) 1285329Smckusic i = NDADDR * sblock->fs_frag; 1294777Smckusic else 1305329Smckusic i = howmany(ip->di_size, sblock->fs_fsize); 1314777Smckusic blksout(&ip->di_db[0], i); 1325329Smckusic size = ip->di_size - NDADDR * sblock->fs_bsize; 1334777Smckusic if (size <= 0) 1344777Smckusic return; 1354777Smckusic for (i = 0; i < NIADDR; i++) { 1364777Smckusic dmpindir(ip->di_ib[i], i, &size); 1374777Smckusic if (size <= 0) 1384777Smckusic return; 1394777Smckusic } 1401426Sroot } 1411426Sroot 1424777Smckusic dmpindir(blk, lvl, size) 1434777Smckusic daddr_t blk; 1444777Smckusic int lvl; 1454777Smckusic long *size; 1461426Sroot { 1474777Smckusic int i, cnt; 1485329Smckusic daddr_t idblk[MAXNINDIR]; 1491426Sroot 1504777Smckusic if (blk != 0) 1515329Smckusic bread(fsbtodb(sblock, blk), (char *)idblk, sblock->fs_bsize); 1524777Smckusic else 15310911Ssam bzero(idblk, sblock->fs_bsize); 1544777Smckusic if (lvl <= 0) { 1555329Smckusic if (*size < NINDIR(sblock) * sblock->fs_bsize) 1565329Smckusic cnt = howmany(*size, sblock->fs_fsize); 1574777Smckusic else 1585329Smckusic cnt = NINDIR(sblock) * sblock->fs_frag; 1595329Smckusic *size -= NINDIR(sblock) * sblock->fs_bsize; 1604777Smckusic blksout(&idblk[0], cnt); 1614777Smckusic return; 1621426Sroot } 1634777Smckusic lvl--; 1645329Smckusic for (i = 0; i < NINDIR(sblock); i++) { 1654777Smckusic dmpindir(idblk[i], lvl, size); 1664777Smckusic if (*size <= 0) 1674777Smckusic return; 1684777Smckusic } 1691426Sroot } 1701426Sroot 1714777Smckusic blksout(blkp, frags) 1724777Smckusic daddr_t *blkp; 1734777Smckusic int frags; 1744777Smckusic { 1755329Smckusic int i, j, count, blks, tbperdb; 1764777Smckusic 1779403Smckusick blks = howmany(frags * sblock->fs_fsize, TP_BSIZE); 1788537Smckusick tbperdb = sblock->fs_bsize / TP_BSIZE; 1794777Smckusic for (i = 0; i < blks; i += TP_NINDIR) { 1804777Smckusic if (i + TP_NINDIR > blks) 1814777Smckusic count = blks; 1824777Smckusic else 1834777Smckusic count = i + TP_NINDIR; 1844777Smckusic for (j = i; j < count; j++) 1855329Smckusic if (blkp[j / tbperdb] != 0) 1864777Smckusic spcl.c_addr[j - i] = 1; 1874777Smckusic else 1884777Smckusic spcl.c_addr[j - i] = 0; 1894777Smckusic spcl.c_count = count - i; 1904777Smckusic spclrec(); 1915329Smckusic for (j = i; j < count; j += tbperdb) 1925329Smckusic if (blkp[j / tbperdb] != 0) 1935329Smckusic if (j + tbperdb <= count) 1945329Smckusic dmpblk(blkp[j / tbperdb], 1955329Smckusic sblock->fs_bsize); 1964777Smckusic else 1975329Smckusic dmpblk(blkp[j / tbperdb], 1984777Smckusic (count - j) * TP_BSIZE); 1994777Smckusic spcl.c_type = TS_ADDR; 2004777Smckusic } 2014777Smckusic } 2024777Smckusic 2031426Sroot bitmap(map, typ) 2045329Smckusic char *map; 2051426Sroot { 2061426Sroot register i, n; 2071426Sroot char *cp; 2081426Sroot 2091426Sroot n = -1; 2105329Smckusic for (i = 0; i < msiz; i++) 2111426Sroot if(map[i]) 2121426Sroot n = i; 2135329Smckusic if (n < 0) 2141426Sroot return; 2155329Smckusic n++; 2161426Sroot spcl.c_type = typ; 2175329Smckusic spcl.c_count = howmany(n * sizeof(map[0]), TP_BSIZE); 2181426Sroot spclrec(); 2195329Smckusic for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE) 2201426Sroot taprec(cp); 2211426Sroot } 2221426Sroot 2231426Sroot spclrec() 2241426Sroot { 2254777Smckusic register int s, i, *ip; 2261426Sroot 2271426Sroot spcl.c_inumber = ino; 2288368Smckusick spcl.c_magic = NFS_MAGIC; 2291426Sroot spcl.c_checksum = 0; 2301426Sroot ip = (int *)&spcl; 2311426Sroot s = 0; 2324777Smckusic for(i = 0; i < sizeof(union u_spcl)/sizeof(int); i++) 2331426Sroot s += *ip++; 2341426Sroot spcl.c_checksum = CHECKSUM - s; 2351426Sroot taprec((char *)&spcl); 2361426Sroot } 2371426Sroot 23814928Smckusick dsrch(d, size, filesize) 2394777Smckusic daddr_t d; 24014928Smckusick int size, filesize; 2411426Sroot { 2425942Smckusic register struct direct *dp; 2435942Smckusic long loc; 2445942Smckusic char dblk[MAXBSIZE]; 2451426Sroot 2461426Sroot if(dadded) 2471426Sroot return; 24814928Smckusick if (filesize > size) 24914928Smckusick filesize = size; 250*15095Smckusick bread(fsbtodb(sblock, d), dblk, filesize); 25114928Smckusick for (loc = 0; loc < filesize; ) { 2525942Smckusic dp = (struct direct *)(dblk + loc); 25314928Smckusick if (dp->d_reclen == 0) { 25414928Smckusick msg("corrupted directory, inumber %d\n", ino); 2555942Smckusic break; 25614928Smckusick } 2575942Smckusic loc += dp->d_reclen; 2585942Smckusic if(dp->d_ino == 0) 2591426Sroot continue; 2605942Smckusic if(dp->d_name[0] == '.') { 2615942Smckusic if(dp->d_name[1] == '\0') 2621426Sroot continue; 2635942Smckusic if(dp->d_name[1] == '.' && dp->d_name[2] == '\0') 2641426Sroot continue; 2651426Sroot } 2665942Smckusic if(BIT(dp->d_ino, nodmap)) { 2671426Sroot dadded++; 2681426Sroot return; 2691426Sroot } 2705942Smckusic if(BIT(dp->d_ino, dirmap)) 2711426Sroot nsubdir++; 2721426Sroot } 2731426Sroot } 2741426Sroot 2754702Smckusic struct dinode * 2764702Smckusic getino(ino) 2774702Smckusic daddr_t ino; 2784702Smckusic { 2794702Smckusic static daddr_t minino, maxino; 2805329Smckusic static struct dinode itab[MAXINOPB]; 2814702Smckusic 2824702Smckusic if (ino >= minino && ino < maxino) { 2834702Smckusic return (&itab[ino - minino]); 2844702Smckusic } 2855386Smckusic bread(fsbtodb(sblock, itod(sblock, ino)), itab, sblock->fs_bsize); 2865329Smckusic minino = ino - (ino % INOPB(sblock)); 2875329Smckusic maxino = minino + INOPB(sblock); 2884702Smckusic return (&itab[ino - minino]); 2894702Smckusic } 2904702Smckusic 2911426Sroot int breaderrors = 0; 2921426Sroot #define BREADEMAX 32 2931426Sroot 294*15095Smckusick bread(da, ba, cnt) 2951426Sroot daddr_t da; 2961426Sroot char *ba; 297*15095Smckusick int cnt; 2981426Sroot { 299*15095Smckusick int n; 3001426Sroot 301*15095Smckusick loop: 3025329Smckusic if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0){ 3031426Sroot msg("bread: lseek fails\n"); 3041426Sroot } 305*15095Smckusick n = read(fi, ba, cnt); 306*15095Smckusick if (n == cnt) 307*15095Smckusick return; 308*15095Smckusick if (da + (cnt / DEV_BSIZE) > fsbtodb(sblock, sblock->fs_size)) { 309*15095Smckusick /* 310*15095Smckusick * Trying to read the final fragment. 311*15095Smckusick * 312*15095Smckusick * NB - dump only works in TP_BSIZE blocks, hence 313*15095Smckusick * rounds DEV_BSIZE fragments up to TP_BSIZE pieces. 314*15095Smckusick * It should be smarter about not actually trying to 315*15095Smckusick * read more than it can get, but for the time being 316*15095Smckusick * we punt and scale back the read only when it gets 317*15095Smckusick * us into trouble. (mkm 9/25/83) 318*15095Smckusick */ 319*15095Smckusick cnt -= DEV_BSIZE; 320*15095Smckusick goto loop; 3211426Sroot } 322*15095Smckusick msg("(This should not happen)bread from %s [block %d]: count=%d, got=%d\n", 323*15095Smckusick disk, da, cnt, n); 324*15095Smckusick if (++breaderrors > BREADEMAX){ 325*15095Smckusick msg("More than %d block read errors from %d\n", 326*15095Smckusick BREADEMAX, disk); 327*15095Smckusick broadcast("DUMP IS AILING!\n"); 328*15095Smckusick msg("This is an unrecoverable error.\n"); 329*15095Smckusick if (!query("Do you want to attempt to continue?")){ 330*15095Smckusick dumpabort(); 331*15095Smckusick /*NOTREACHED*/ 332*15095Smckusick } else 333*15095Smckusick breaderrors = 0; 334*15095Smckusick } 3351426Sroot } 336