1*16134Smckusick static char *sccsid = "@(#)traverse.c 1.16 (Berkeley) 03/08/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 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 { 206*16134Smckusick register i; 2071426Sroot char *cp; 2081426Sroot 2091426Sroot spcl.c_type = typ; 210*16134Smckusick spcl.c_count = howmany(msiz * sizeof(map[0]), TP_BSIZE); 2111426Sroot spclrec(); 2125329Smckusic for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE) 2131426Sroot taprec(cp); 2141426Sroot } 2151426Sroot 2161426Sroot spclrec() 2171426Sroot { 2184777Smckusic register int s, i, *ip; 2191426Sroot 2201426Sroot spcl.c_inumber = ino; 2218368Smckusick spcl.c_magic = NFS_MAGIC; 2221426Sroot spcl.c_checksum = 0; 2231426Sroot ip = (int *)&spcl; 2241426Sroot s = 0; 2254777Smckusic for(i = 0; i < sizeof(union u_spcl)/sizeof(int); i++) 2261426Sroot s += *ip++; 2271426Sroot spcl.c_checksum = CHECKSUM - s; 2281426Sroot taprec((char *)&spcl); 2291426Sroot } 2301426Sroot 23114928Smckusick dsrch(d, size, filesize) 2324777Smckusic daddr_t d; 23314928Smckusick int size, filesize; 2341426Sroot { 2355942Smckusic register struct direct *dp; 2365942Smckusic long loc; 2375942Smckusic char dblk[MAXBSIZE]; 2381426Sroot 2391426Sroot if(dadded) 2401426Sroot return; 24114928Smckusick if (filesize > size) 24214928Smckusick filesize = size; 24315095Smckusick bread(fsbtodb(sblock, d), dblk, filesize); 24414928Smckusick for (loc = 0; loc < filesize; ) { 2455942Smckusic dp = (struct direct *)(dblk + loc); 24614928Smckusick if (dp->d_reclen == 0) { 24714928Smckusick msg("corrupted directory, inumber %d\n", ino); 2485942Smckusic break; 24914928Smckusick } 2505942Smckusic loc += dp->d_reclen; 2515942Smckusic if(dp->d_ino == 0) 2521426Sroot continue; 2535942Smckusic if(dp->d_name[0] == '.') { 2545942Smckusic if(dp->d_name[1] == '\0') 2551426Sroot continue; 2565942Smckusic if(dp->d_name[1] == '.' && dp->d_name[2] == '\0') 2571426Sroot continue; 2581426Sroot } 2595942Smckusic if(BIT(dp->d_ino, nodmap)) { 2601426Sroot dadded++; 2611426Sroot return; 2621426Sroot } 2635942Smckusic if(BIT(dp->d_ino, dirmap)) 2641426Sroot nsubdir++; 2651426Sroot } 2661426Sroot } 2671426Sroot 2684702Smckusic struct dinode * 2694702Smckusic getino(ino) 2704702Smckusic daddr_t ino; 2714702Smckusic { 2724702Smckusic static daddr_t minino, maxino; 2735329Smckusic static struct dinode itab[MAXINOPB]; 2744702Smckusic 2754702Smckusic if (ino >= minino && ino < maxino) { 2764702Smckusic return (&itab[ino - minino]); 2774702Smckusic } 2785386Smckusic bread(fsbtodb(sblock, itod(sblock, ino)), itab, sblock->fs_bsize); 2795329Smckusic minino = ino - (ino % INOPB(sblock)); 2805329Smckusic maxino = minino + INOPB(sblock); 2814702Smckusic return (&itab[ino - minino]); 2824702Smckusic } 2834702Smckusic 2841426Sroot int breaderrors = 0; 2851426Sroot #define BREADEMAX 32 2861426Sroot 28715095Smckusick bread(da, ba, cnt) 2881426Sroot daddr_t da; 2891426Sroot char *ba; 29015095Smckusick int cnt; 2911426Sroot { 29215095Smckusick int n; 2931426Sroot 29415095Smckusick loop: 2955329Smckusic if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0){ 2961426Sroot msg("bread: lseek fails\n"); 2971426Sroot } 29815095Smckusick n = read(fi, ba, cnt); 29915095Smckusick if (n == cnt) 30015095Smckusick return; 30115095Smckusick if (da + (cnt / DEV_BSIZE) > fsbtodb(sblock, sblock->fs_size)) { 30215095Smckusick /* 30315095Smckusick * Trying to read the final fragment. 30415095Smckusick * 30515095Smckusick * NB - dump only works in TP_BSIZE blocks, hence 30615095Smckusick * rounds DEV_BSIZE fragments up to TP_BSIZE pieces. 30715095Smckusick * It should be smarter about not actually trying to 30815095Smckusick * read more than it can get, but for the time being 30915095Smckusick * we punt and scale back the read only when it gets 31015095Smckusick * us into trouble. (mkm 9/25/83) 31115095Smckusick */ 31215095Smckusick cnt -= DEV_BSIZE; 31315095Smckusick goto loop; 3141426Sroot } 31515095Smckusick msg("(This should not happen)bread from %s [block %d]: count=%d, got=%d\n", 31615095Smckusick disk, da, cnt, n); 31715095Smckusick if (++breaderrors > BREADEMAX){ 31815095Smckusick msg("More than %d block read errors from %d\n", 31915095Smckusick BREADEMAX, disk); 32015095Smckusick broadcast("DUMP IS AILING!\n"); 32115095Smckusick msg("This is an unrecoverable error.\n"); 32215095Smckusick if (!query("Do you want to attempt to continue?")){ 32315095Smckusick dumpabort(); 32415095Smckusick /*NOTREACHED*/ 32515095Smckusick } else 32615095Smckusick breaderrors = 0; 32715095Smckusick } 3281426Sroot } 329