122041Sdist /* 222041Sdist * Copyright (c) 1980 Regents of the University of California. 322041Sdist * All rights reserved. The Berkeley software License Agreement 422041Sdist * specifies the terms and conditions for redistribution. 522041Sdist */ 65329Smckusic 722041Sdist #ifndef lint 8*25797Smckusick static char sccsid[] = "@(#)traverse.c 5.3 (Berkeley) 01/09/86"; 922041Sdist #endif not lint 1022041Sdist 111426Sroot #include "dump.h" 121426Sroot 131426Sroot pass(fn, map) 14*25797Smckusick register int (*fn)(); 15*25797Smckusick register char *map; 161426Sroot { 17*25797Smckusick register int bits; 184702Smckusic ino_t maxino; 191426Sroot 205329Smckusic maxino = sblock->fs_ipg * sblock->fs_ncg - 1; 214702Smckusic for (ino = 0; ino < maxino; ) { 22*25797Smckusick if ((ino % NBBY) == 0) { 234702Smckusic bits = ~0; 24*25797Smckusick if (map != NULL) 254702Smckusic bits = *map++; 261426Sroot } 274702Smckusic ino++; 28*25797Smckusick if (bits & 1) 29*25797Smckusick (*fn)(getino(ino)); 304702Smckusic bits >>= 1; 311426Sroot } 321426Sroot } 331426Sroot 341426Sroot mark(ip) 354777Smckusic struct dinode *ip; 361426Sroot { 37*25797Smckusick register int f; 38*25797Smckusick extern int anydskipped; 391426Sroot 401426Sroot f = ip->di_mode & IFMT; 41*25797Smckusick if (f == 0) 421426Sroot return; 431426Sroot BIS(ino, clrmap); 44*25797Smckusick if (f == IFDIR) 451426Sroot BIS(ino, dirmap); 465329Smckusic if ((ip->di_mtime >= spcl.c_ddate || ip->di_ctime >= spcl.c_ddate) && 475329Smckusic !BIT(ino, nodmap)) { 481426Sroot BIS(ino, nodmap); 496288Smckusick if (f != IFREG && f != IFDIR && f != IFLNK) { 501426Sroot esize += 1; 511426Sroot return; 521426Sroot } 531426Sroot est(ip); 54*25797Smckusick } else if (f == IFDIR) 55*25797Smckusick anydskipped = 1; 561426Sroot } 571426Sroot 581426Sroot add(ip) 595329Smckusic register struct dinode *ip; 601426Sroot { 615329Smckusic register int i; 6214928Smckusick long filesize; 631426Sroot 641426Sroot if(BIT(ino, nodmap)) 651426Sroot return; 661426Sroot nsubdir = 0; 671426Sroot dadded = 0; 6814928Smckusick filesize = ip->di_size; 695329Smckusic for (i = 0; i < NDADDR; i++) { 705329Smckusic if (ip->di_db[i] != 0) 7114928Smckusick dsrch(ip->di_db[i], dblksize(sblock, ip, i), filesize); 7214928Smckusick filesize -= sblock->fs_bsize; 735329Smckusic } 745329Smckusic for (i = 0; i < NIADDR; i++) { 755329Smckusic if (ip->di_ib[i] != 0) 7614928Smckusick indir(ip->di_ib[i], i, &filesize); 775329Smckusic } 781426Sroot if(dadded) { 791426Sroot nadded++; 805329Smckusic if (!BIT(ino, nodmap)) { 815329Smckusic BIS(ino, nodmap); 825329Smckusic est(ip); 835329Smckusic } 841426Sroot } 851426Sroot if(nsubdir == 0) 861426Sroot if(!BIT(ino, nodmap)) 871426Sroot BIC(ino, dirmap); 881426Sroot } 891426Sroot 9014928Smckusick indir(d, n, filesize) 915329Smckusic daddr_t d; 9214928Smckusick int n, *filesize; 935329Smckusic { 945329Smckusic register i; 955329Smckusic daddr_t idblk[MAXNINDIR]; 965329Smckusic 975329Smckusic bread(fsbtodb(sblock, d), (char *)idblk, sblock->fs_bsize); 985329Smckusic if(n <= 0) { 995329Smckusic for(i=0; i < NINDIR(sblock); i++) { 1005329Smckusic d = idblk[i]; 1015329Smckusic if(d != 0) 10214928Smckusick dsrch(d, sblock->fs_bsize, *filesize); 10314928Smckusick *filesize -= sblock->fs_bsize; 1045329Smckusic } 1055329Smckusic } else { 1065329Smckusic n--; 1075329Smckusic for(i=0; i < NINDIR(sblock); i++) { 1085329Smckusic d = idblk[i]; 1095329Smckusic if(d != 0) 11014928Smckusick indir(d, n, filesize); 1115329Smckusic } 1125329Smckusic } 1135329Smckusic } 1145329Smckusic 11517234Smckusick dirdump(ip) 11617234Smckusick struct dinode *ip; 11717234Smckusick { 11817234Smckusick /* watchout for dir inodes deleted and maybe reallocated */ 11917234Smckusick if ((ip->di_mode & IFMT) != IFDIR) 12017234Smckusick return; 12117234Smckusick dump(ip); 12217234Smckusick } 12317234Smckusick 1241426Sroot dump(ip) 1254777Smckusic struct dinode *ip; 1261426Sroot { 1274777Smckusic register int i; 1284777Smckusic long size; 1291426Sroot 1301426Sroot if(newtape) { 1311426Sroot newtape = 0; 1321426Sroot bitmap(nodmap, TS_BITS); 1331426Sroot } 1341426Sroot BIC(ino, nodmap); 1351426Sroot spcl.c_dinode = *ip; 1361426Sroot spcl.c_type = TS_INODE; 1371426Sroot spcl.c_count = 0; 1381426Sroot i = ip->di_mode & IFMT; 13917234Smckusick if (i == 0) /* free inode */ 14017234Smckusick return; 1416288Smckusick if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) { 1421426Sroot spclrec(); 1431426Sroot return; 1441426Sroot } 1455329Smckusic if (ip->di_size > NDADDR * sblock->fs_bsize) 1465329Smckusic i = NDADDR * sblock->fs_frag; 1474777Smckusic else 1485329Smckusic i = howmany(ip->di_size, sblock->fs_fsize); 1494777Smckusic blksout(&ip->di_db[0], i); 1505329Smckusic size = ip->di_size - NDADDR * sblock->fs_bsize; 1514777Smckusic if (size <= 0) 1524777Smckusic return; 1534777Smckusic for (i = 0; i < NIADDR; i++) { 1544777Smckusic dmpindir(ip->di_ib[i], i, &size); 1554777Smckusic if (size <= 0) 1564777Smckusic return; 1574777Smckusic } 1581426Sroot } 1591426Sroot 1604777Smckusic dmpindir(blk, lvl, size) 1614777Smckusic daddr_t blk; 1624777Smckusic int lvl; 1634777Smckusic long *size; 1641426Sroot { 1654777Smckusic int i, cnt; 1665329Smckusic daddr_t idblk[MAXNINDIR]; 1671426Sroot 1684777Smckusic if (blk != 0) 1695329Smckusic bread(fsbtodb(sblock, blk), (char *)idblk, sblock->fs_bsize); 1704777Smckusic else 17110911Ssam bzero(idblk, sblock->fs_bsize); 1724777Smckusic if (lvl <= 0) { 1735329Smckusic if (*size < NINDIR(sblock) * sblock->fs_bsize) 1745329Smckusic cnt = howmany(*size, sblock->fs_fsize); 1754777Smckusic else 1765329Smckusic cnt = NINDIR(sblock) * sblock->fs_frag; 1775329Smckusic *size -= NINDIR(sblock) * sblock->fs_bsize; 1784777Smckusic blksout(&idblk[0], cnt); 1794777Smckusic return; 1801426Sroot } 1814777Smckusic lvl--; 1825329Smckusic for (i = 0; i < NINDIR(sblock); i++) { 1834777Smckusic dmpindir(idblk[i], lvl, size); 1844777Smckusic if (*size <= 0) 1854777Smckusic return; 1864777Smckusic } 1871426Sroot } 1881426Sroot 1894777Smckusic blksout(blkp, frags) 1904777Smckusic daddr_t *blkp; 1914777Smckusic int frags; 1924777Smckusic { 1935329Smckusic int i, j, count, blks, tbperdb; 1944777Smckusic 1959403Smckusick blks = howmany(frags * sblock->fs_fsize, TP_BSIZE); 1968537Smckusick tbperdb = sblock->fs_bsize / TP_BSIZE; 1974777Smckusic for (i = 0; i < blks; i += TP_NINDIR) { 1984777Smckusic if (i + TP_NINDIR > blks) 1994777Smckusic count = blks; 2004777Smckusic else 2014777Smckusic count = i + TP_NINDIR; 2024777Smckusic for (j = i; j < count; j++) 2035329Smckusic if (blkp[j / tbperdb] != 0) 2044777Smckusic spcl.c_addr[j - i] = 1; 2054777Smckusic else 2064777Smckusic spcl.c_addr[j - i] = 0; 2074777Smckusic spcl.c_count = count - i; 2084777Smckusic spclrec(); 2095329Smckusic for (j = i; j < count; j += tbperdb) 2105329Smckusic if (blkp[j / tbperdb] != 0) 2115329Smckusic if (j + tbperdb <= count) 2125329Smckusic dmpblk(blkp[j / tbperdb], 2135329Smckusic sblock->fs_bsize); 2144777Smckusic else 2155329Smckusic dmpblk(blkp[j / tbperdb], 2164777Smckusic (count - j) * TP_BSIZE); 2174777Smckusic spcl.c_type = TS_ADDR; 2184777Smckusic } 2194777Smckusic } 2204777Smckusic 2211426Sroot bitmap(map, typ) 2225329Smckusic char *map; 2231426Sroot { 22416134Smckusick register i; 2251426Sroot char *cp; 2261426Sroot 2271426Sroot spcl.c_type = typ; 22816134Smckusick spcl.c_count = howmany(msiz * sizeof(map[0]), TP_BSIZE); 2291426Sroot spclrec(); 2305329Smckusic for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE) 2311426Sroot taprec(cp); 2321426Sroot } 2331426Sroot 2341426Sroot spclrec() 2351426Sroot { 2364777Smckusic register int s, i, *ip; 2371426Sroot 2381426Sroot spcl.c_inumber = ino; 2398368Smckusick spcl.c_magic = NFS_MAGIC; 2401426Sroot spcl.c_checksum = 0; 2411426Sroot ip = (int *)&spcl; 2421426Sroot s = 0; 24324168Smckusick i = sizeof(union u_spcl) / (4*sizeof(int)); 24424168Smckusick while (--i >= 0) { 24524168Smckusick s += *ip++; s += *ip++; 24624168Smckusick s += *ip++; s += *ip++; 24724168Smckusick } 2481426Sroot spcl.c_checksum = CHECKSUM - s; 2491426Sroot taprec((char *)&spcl); 2501426Sroot } 2511426Sroot 25214928Smckusick dsrch(d, size, filesize) 2534777Smckusic daddr_t d; 25414928Smckusick int size, filesize; 2551426Sroot { 2565942Smckusic register struct direct *dp; 2575942Smckusic long loc; 2585942Smckusic char dblk[MAXBSIZE]; 2591426Sroot 2601426Sroot if(dadded) 2611426Sroot return; 26214928Smckusick if (filesize > size) 26314928Smckusick filesize = size; 26415095Smckusick bread(fsbtodb(sblock, d), dblk, filesize); 26514928Smckusick for (loc = 0; loc < filesize; ) { 2665942Smckusic dp = (struct direct *)(dblk + loc); 26714928Smckusick if (dp->d_reclen == 0) { 26814928Smckusick msg("corrupted directory, inumber %d\n", ino); 2695942Smckusic break; 27014928Smckusick } 2715942Smckusic loc += dp->d_reclen; 2725942Smckusic if(dp->d_ino == 0) 2731426Sroot continue; 2745942Smckusic if(dp->d_name[0] == '.') { 2755942Smckusic if(dp->d_name[1] == '\0') 2761426Sroot continue; 2775942Smckusic if(dp->d_name[1] == '.' && dp->d_name[2] == '\0') 2781426Sroot continue; 2791426Sroot } 2805942Smckusic if(BIT(dp->d_ino, nodmap)) { 2811426Sroot dadded++; 2821426Sroot return; 2831426Sroot } 2845942Smckusic if(BIT(dp->d_ino, dirmap)) 2851426Sroot nsubdir++; 2861426Sroot } 2871426Sroot } 2881426Sroot 2894702Smckusic struct dinode * 2904702Smckusic getino(ino) 2914702Smckusic daddr_t ino; 2924702Smckusic { 2934702Smckusic static daddr_t minino, maxino; 2945329Smckusic static struct dinode itab[MAXINOPB]; 2954702Smckusic 2964702Smckusic if (ino >= minino && ino < maxino) { 2974702Smckusic return (&itab[ino - minino]); 2984702Smckusic } 2995386Smckusic bread(fsbtodb(sblock, itod(sblock, ino)), itab, sblock->fs_bsize); 3005329Smckusic minino = ino - (ino % INOPB(sblock)); 3015329Smckusic maxino = minino + INOPB(sblock); 3024702Smckusic return (&itab[ino - minino]); 3034702Smckusic } 3044702Smckusic 3051426Sroot int breaderrors = 0; 3061426Sroot #define BREADEMAX 32 3071426Sroot 30815095Smckusick bread(da, ba, cnt) 3091426Sroot daddr_t da; 3101426Sroot char *ba; 31115095Smckusick int cnt; 3121426Sroot { 31315095Smckusick int n; 3141426Sroot 31515095Smckusick loop: 3165329Smckusic if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0){ 3171426Sroot msg("bread: lseek fails\n"); 3181426Sroot } 31915095Smckusick n = read(fi, ba, cnt); 32015095Smckusick if (n == cnt) 32115095Smckusick return; 32215095Smckusick if (da + (cnt / DEV_BSIZE) > fsbtodb(sblock, sblock->fs_size)) { 32315095Smckusick /* 32415095Smckusick * Trying to read the final fragment. 32515095Smckusick * 32615095Smckusick * NB - dump only works in TP_BSIZE blocks, hence 32715095Smckusick * rounds DEV_BSIZE fragments up to TP_BSIZE pieces. 32815095Smckusick * It should be smarter about not actually trying to 32915095Smckusick * read more than it can get, but for the time being 33015095Smckusick * we punt and scale back the read only when it gets 33115095Smckusick * us into trouble. (mkm 9/25/83) 33215095Smckusick */ 33315095Smckusick cnt -= DEV_BSIZE; 33415095Smckusick goto loop; 3351426Sroot } 33615095Smckusick msg("(This should not happen)bread from %s [block %d]: count=%d, got=%d\n", 33715095Smckusick disk, da, cnt, n); 33815095Smckusick if (++breaderrors > BREADEMAX){ 33915095Smckusick msg("More than %d block read errors from %d\n", 34015095Smckusick BREADEMAX, disk); 34115095Smckusick broadcast("DUMP IS AILING!\n"); 34215095Smckusick msg("This is an unrecoverable error.\n"); 34315095Smckusick if (!query("Do you want to attempt to continue?")){ 34415095Smckusick dumpabort(); 34515095Smckusick /*NOTREACHED*/ 34615095Smckusick } else 34715095Smckusick breaderrors = 0; 34815095Smckusick } 3491426Sroot } 350