1*17234Smckusick static char *sccsid = "@(#)traverse.c 1.17 (Berkeley) 10/05/84"; 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 108*17234Smckusick dirdump(ip) 109*17234Smckusick struct dinode *ip; 110*17234Smckusick { 111*17234Smckusick /* watchout for dir inodes deleted and maybe reallocated */ 112*17234Smckusick if ((ip->di_mode & IFMT) != IFDIR) 113*17234Smckusick return; 114*17234Smckusick dump(ip); 115*17234Smckusick } 116*17234Smckusick 1171426Sroot dump(ip) 1184777Smckusic struct dinode *ip; 1191426Sroot { 1204777Smckusic register int i; 1214777Smckusic long size; 1221426Sroot 1231426Sroot if(newtape) { 1241426Sroot newtape = 0; 1251426Sroot bitmap(nodmap, TS_BITS); 1261426Sroot } 1271426Sroot BIC(ino, nodmap); 1281426Sroot spcl.c_dinode = *ip; 1291426Sroot spcl.c_type = TS_INODE; 1301426Sroot spcl.c_count = 0; 1311426Sroot i = ip->di_mode & IFMT; 132*17234Smckusick if (i == 0) /* free inode */ 133*17234Smckusick return; 1346288Smckusick if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) { 1351426Sroot spclrec(); 1361426Sroot return; 1371426Sroot } 1385329Smckusic if (ip->di_size > NDADDR * sblock->fs_bsize) 1395329Smckusic i = NDADDR * sblock->fs_frag; 1404777Smckusic else 1415329Smckusic i = howmany(ip->di_size, sblock->fs_fsize); 1424777Smckusic blksout(&ip->di_db[0], i); 1435329Smckusic size = ip->di_size - NDADDR * sblock->fs_bsize; 1444777Smckusic if (size <= 0) 1454777Smckusic return; 1464777Smckusic for (i = 0; i < NIADDR; i++) { 1474777Smckusic dmpindir(ip->di_ib[i], i, &size); 1484777Smckusic if (size <= 0) 1494777Smckusic return; 1504777Smckusic } 1511426Sroot } 1521426Sroot 1534777Smckusic dmpindir(blk, lvl, size) 1544777Smckusic daddr_t blk; 1554777Smckusic int lvl; 1564777Smckusic long *size; 1571426Sroot { 1584777Smckusic int i, cnt; 1595329Smckusic daddr_t idblk[MAXNINDIR]; 1601426Sroot 1614777Smckusic if (blk != 0) 1625329Smckusic bread(fsbtodb(sblock, blk), (char *)idblk, sblock->fs_bsize); 1634777Smckusic else 16410911Ssam bzero(idblk, sblock->fs_bsize); 1654777Smckusic if (lvl <= 0) { 1665329Smckusic if (*size < NINDIR(sblock) * sblock->fs_bsize) 1675329Smckusic cnt = howmany(*size, sblock->fs_fsize); 1684777Smckusic else 1695329Smckusic cnt = NINDIR(sblock) * sblock->fs_frag; 1705329Smckusic *size -= NINDIR(sblock) * sblock->fs_bsize; 1714777Smckusic blksout(&idblk[0], cnt); 1724777Smckusic return; 1731426Sroot } 1744777Smckusic lvl--; 1755329Smckusic for (i = 0; i < NINDIR(sblock); i++) { 1764777Smckusic dmpindir(idblk[i], lvl, size); 1774777Smckusic if (*size <= 0) 1784777Smckusic return; 1794777Smckusic } 1801426Sroot } 1811426Sroot 1824777Smckusic blksout(blkp, frags) 1834777Smckusic daddr_t *blkp; 1844777Smckusic int frags; 1854777Smckusic { 1865329Smckusic int i, j, count, blks, tbperdb; 1874777Smckusic 1889403Smckusick blks = howmany(frags * sblock->fs_fsize, TP_BSIZE); 1898537Smckusick tbperdb = sblock->fs_bsize / TP_BSIZE; 1904777Smckusic for (i = 0; i < blks; i += TP_NINDIR) { 1914777Smckusic if (i + TP_NINDIR > blks) 1924777Smckusic count = blks; 1934777Smckusic else 1944777Smckusic count = i + TP_NINDIR; 1954777Smckusic for (j = i; j < count; j++) 1965329Smckusic if (blkp[j / tbperdb] != 0) 1974777Smckusic spcl.c_addr[j - i] = 1; 1984777Smckusic else 1994777Smckusic spcl.c_addr[j - i] = 0; 2004777Smckusic spcl.c_count = count - i; 2014777Smckusic spclrec(); 2025329Smckusic for (j = i; j < count; j += tbperdb) 2035329Smckusic if (blkp[j / tbperdb] != 0) 2045329Smckusic if (j + tbperdb <= count) 2055329Smckusic dmpblk(blkp[j / tbperdb], 2065329Smckusic sblock->fs_bsize); 2074777Smckusic else 2085329Smckusic dmpblk(blkp[j / tbperdb], 2094777Smckusic (count - j) * TP_BSIZE); 2104777Smckusic spcl.c_type = TS_ADDR; 2114777Smckusic } 2124777Smckusic } 2134777Smckusic 2141426Sroot bitmap(map, typ) 2155329Smckusic char *map; 2161426Sroot { 21716134Smckusick register i; 2181426Sroot char *cp; 2191426Sroot 2201426Sroot spcl.c_type = typ; 22116134Smckusick spcl.c_count = howmany(msiz * sizeof(map[0]), TP_BSIZE); 2221426Sroot spclrec(); 2235329Smckusic for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE) 2241426Sroot taprec(cp); 2251426Sroot } 2261426Sroot 2271426Sroot spclrec() 2281426Sroot { 2294777Smckusic register int s, i, *ip; 2301426Sroot 2311426Sroot spcl.c_inumber = ino; 2328368Smckusick spcl.c_magic = NFS_MAGIC; 2331426Sroot spcl.c_checksum = 0; 2341426Sroot ip = (int *)&spcl; 2351426Sroot s = 0; 2364777Smckusic for(i = 0; i < sizeof(union u_spcl)/sizeof(int); i++) 2371426Sroot s += *ip++; 2381426Sroot spcl.c_checksum = CHECKSUM - s; 2391426Sroot taprec((char *)&spcl); 2401426Sroot } 2411426Sroot 24214928Smckusick dsrch(d, size, filesize) 2434777Smckusic daddr_t d; 24414928Smckusick int size, filesize; 2451426Sroot { 2465942Smckusic register struct direct *dp; 2475942Smckusic long loc; 2485942Smckusic char dblk[MAXBSIZE]; 2491426Sroot 2501426Sroot if(dadded) 2511426Sroot return; 25214928Smckusick if (filesize > size) 25314928Smckusick filesize = size; 25415095Smckusick bread(fsbtodb(sblock, d), dblk, filesize); 25514928Smckusick for (loc = 0; loc < filesize; ) { 2565942Smckusic dp = (struct direct *)(dblk + loc); 25714928Smckusick if (dp->d_reclen == 0) { 25814928Smckusick msg("corrupted directory, inumber %d\n", ino); 2595942Smckusic break; 26014928Smckusick } 2615942Smckusic loc += dp->d_reclen; 2625942Smckusic if(dp->d_ino == 0) 2631426Sroot continue; 2645942Smckusic if(dp->d_name[0] == '.') { 2655942Smckusic if(dp->d_name[1] == '\0') 2661426Sroot continue; 2675942Smckusic if(dp->d_name[1] == '.' && dp->d_name[2] == '\0') 2681426Sroot continue; 2691426Sroot } 2705942Smckusic if(BIT(dp->d_ino, nodmap)) { 2711426Sroot dadded++; 2721426Sroot return; 2731426Sroot } 2745942Smckusic if(BIT(dp->d_ino, dirmap)) 2751426Sroot nsubdir++; 2761426Sroot } 2771426Sroot } 2781426Sroot 2794702Smckusic struct dinode * 2804702Smckusic getino(ino) 2814702Smckusic daddr_t ino; 2824702Smckusic { 2834702Smckusic static daddr_t minino, maxino; 2845329Smckusic static struct dinode itab[MAXINOPB]; 2854702Smckusic 2864702Smckusic if (ino >= minino && ino < maxino) { 2874702Smckusic return (&itab[ino - minino]); 2884702Smckusic } 2895386Smckusic bread(fsbtodb(sblock, itod(sblock, ino)), itab, sblock->fs_bsize); 2905329Smckusic minino = ino - (ino % INOPB(sblock)); 2915329Smckusic maxino = minino + INOPB(sblock); 2924702Smckusic return (&itab[ino - minino]); 2934702Smckusic } 2944702Smckusic 2951426Sroot int breaderrors = 0; 2961426Sroot #define BREADEMAX 32 2971426Sroot 29815095Smckusick bread(da, ba, cnt) 2991426Sroot daddr_t da; 3001426Sroot char *ba; 30115095Smckusick int cnt; 3021426Sroot { 30315095Smckusick int n; 3041426Sroot 30515095Smckusick loop: 3065329Smckusic if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0){ 3071426Sroot msg("bread: lseek fails\n"); 3081426Sroot } 30915095Smckusick n = read(fi, ba, cnt); 31015095Smckusick if (n == cnt) 31115095Smckusick return; 31215095Smckusick if (da + (cnt / DEV_BSIZE) > fsbtodb(sblock, sblock->fs_size)) { 31315095Smckusick /* 31415095Smckusick * Trying to read the final fragment. 31515095Smckusick * 31615095Smckusick * NB - dump only works in TP_BSIZE blocks, hence 31715095Smckusick * rounds DEV_BSIZE fragments up to TP_BSIZE pieces. 31815095Smckusick * It should be smarter about not actually trying to 31915095Smckusick * read more than it can get, but for the time being 32015095Smckusick * we punt and scale back the read only when it gets 32115095Smckusick * us into trouble. (mkm 9/25/83) 32215095Smckusick */ 32315095Smckusick cnt -= DEV_BSIZE; 32415095Smckusick goto loop; 3251426Sroot } 32615095Smckusick msg("(This should not happen)bread from %s [block %d]: count=%d, got=%d\n", 32715095Smckusick disk, da, cnt, n); 32815095Smckusick if (++breaderrors > BREADEMAX){ 32915095Smckusick msg("More than %d block read errors from %d\n", 33015095Smckusick BREADEMAX, disk); 33115095Smckusick broadcast("DUMP IS AILING!\n"); 33215095Smckusick msg("This is an unrecoverable error.\n"); 33315095Smckusick if (!query("Do you want to attempt to continue?")){ 33415095Smckusick dumpabort(); 33515095Smckusick /*NOTREACHED*/ 33615095Smckusick } else 33715095Smckusick breaderrors = 0; 33815095Smckusick } 3391426Sroot } 340