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*24168Smckusick static char sccsid[] = "@(#)traverse.c 5.2 (Berkeley) 08/05/85"; 922041Sdist #endif not lint 1022041Sdist 111426Sroot #include "dump.h" 121426Sroot 131426Sroot pass(fn, map) 144702Smckusic int (*fn)(); 155329Smckusic char *map; 161426Sroot { 174702Smckusic struct dinode *dp; 181426Sroot int bits; 194702Smckusic ino_t maxino; 201426Sroot 215329Smckusic maxino = sblock->fs_ipg * sblock->fs_ncg - 1; 224702Smckusic for (ino = 0; ino < maxino; ) { 235329Smckusic if((ino % NBBY) == 0) { 244702Smckusic bits = ~0; 254702Smckusic if(map != NULL) 264702Smckusic bits = *map++; 271426Sroot } 284702Smckusic ino++; 294702Smckusic if(bits & 1) { 304702Smckusic dp = getino(ino); 314702Smckusic (*fn)(dp); 324702Smckusic } 334702Smckusic bits >>= 1; 341426Sroot } 351426Sroot } 361426Sroot 371426Sroot mark(ip) 384777Smckusic struct dinode *ip; 391426Sroot { 401426Sroot register f; 411426Sroot 421426Sroot f = ip->di_mode & IFMT; 431426Sroot if(f == 0) 441426Sroot return; 451426Sroot BIS(ino, clrmap); 461426Sroot if(f == IFDIR) 471426Sroot BIS(ino, dirmap); 485329Smckusic if ((ip->di_mtime >= spcl.c_ddate || ip->di_ctime >= spcl.c_ddate) && 495329Smckusic !BIT(ino, nodmap)) { 501426Sroot BIS(ino, nodmap); 516288Smckusick if (f != IFREG && f != IFDIR && f != IFLNK) { 521426Sroot esize += 1; 531426Sroot return; 541426Sroot } 551426Sroot est(ip); 561426Sroot } 571426Sroot } 581426Sroot 591426Sroot add(ip) 605329Smckusic register struct dinode *ip; 611426Sroot { 625329Smckusic register int i; 6314928Smckusick long filesize; 641426Sroot 651426Sroot if(BIT(ino, nodmap)) 661426Sroot return; 671426Sroot nsubdir = 0; 681426Sroot dadded = 0; 6914928Smckusick filesize = ip->di_size; 705329Smckusic for (i = 0; i < NDADDR; i++) { 715329Smckusic if (ip->di_db[i] != 0) 7214928Smckusick dsrch(ip->di_db[i], dblksize(sblock, ip, i), filesize); 7314928Smckusick filesize -= sblock->fs_bsize; 745329Smckusic } 755329Smckusic for (i = 0; i < NIADDR; i++) { 765329Smckusic if (ip->di_ib[i] != 0) 7714928Smckusick indir(ip->di_ib[i], i, &filesize); 785329Smckusic } 791426Sroot if(dadded) { 801426Sroot nadded++; 815329Smckusic if (!BIT(ino, nodmap)) { 825329Smckusic BIS(ino, nodmap); 835329Smckusic est(ip); 845329Smckusic } 851426Sroot } 861426Sroot if(nsubdir == 0) 871426Sroot if(!BIT(ino, nodmap)) 881426Sroot BIC(ino, dirmap); 891426Sroot } 901426Sroot 9114928Smckusick indir(d, n, filesize) 925329Smckusic daddr_t d; 9314928Smckusick int n, *filesize; 945329Smckusic { 955329Smckusic register i; 965329Smckusic daddr_t idblk[MAXNINDIR]; 975329Smckusic 985329Smckusic bread(fsbtodb(sblock, d), (char *)idblk, sblock->fs_bsize); 995329Smckusic if(n <= 0) { 1005329Smckusic for(i=0; i < NINDIR(sblock); i++) { 1015329Smckusic d = idblk[i]; 1025329Smckusic if(d != 0) 10314928Smckusick dsrch(d, sblock->fs_bsize, *filesize); 10414928Smckusick *filesize -= sblock->fs_bsize; 1055329Smckusic } 1065329Smckusic } else { 1075329Smckusic n--; 1085329Smckusic for(i=0; i < NINDIR(sblock); i++) { 1095329Smckusic d = idblk[i]; 1105329Smckusic if(d != 0) 11114928Smckusick indir(d, n, filesize); 1125329Smckusic } 1135329Smckusic } 1145329Smckusic } 1155329Smckusic 11617234Smckusick dirdump(ip) 11717234Smckusick struct dinode *ip; 11817234Smckusick { 11917234Smckusick /* watchout for dir inodes deleted and maybe reallocated */ 12017234Smckusick if ((ip->di_mode & IFMT) != IFDIR) 12117234Smckusick return; 12217234Smckusick dump(ip); 12317234Smckusick } 12417234Smckusick 1251426Sroot dump(ip) 1264777Smckusic struct dinode *ip; 1271426Sroot { 1284777Smckusic register int i; 1294777Smckusic long size; 1301426Sroot 1311426Sroot if(newtape) { 1321426Sroot newtape = 0; 1331426Sroot bitmap(nodmap, TS_BITS); 1341426Sroot } 1351426Sroot BIC(ino, nodmap); 1361426Sroot spcl.c_dinode = *ip; 1371426Sroot spcl.c_type = TS_INODE; 1381426Sroot spcl.c_count = 0; 1391426Sroot i = ip->di_mode & IFMT; 14017234Smckusick if (i == 0) /* free inode */ 14117234Smckusick return; 1426288Smckusick if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) { 1431426Sroot spclrec(); 1441426Sroot return; 1451426Sroot } 1465329Smckusic if (ip->di_size > NDADDR * sblock->fs_bsize) 1475329Smckusic i = NDADDR * sblock->fs_frag; 1484777Smckusic else 1495329Smckusic i = howmany(ip->di_size, sblock->fs_fsize); 1504777Smckusic blksout(&ip->di_db[0], i); 1515329Smckusic size = ip->di_size - NDADDR * sblock->fs_bsize; 1524777Smckusic if (size <= 0) 1534777Smckusic return; 1544777Smckusic for (i = 0; i < NIADDR; i++) { 1554777Smckusic dmpindir(ip->di_ib[i], i, &size); 1564777Smckusic if (size <= 0) 1574777Smckusic return; 1584777Smckusic } 1591426Sroot } 1601426Sroot 1614777Smckusic dmpindir(blk, lvl, size) 1624777Smckusic daddr_t blk; 1634777Smckusic int lvl; 1644777Smckusic long *size; 1651426Sroot { 1664777Smckusic int i, cnt; 1675329Smckusic daddr_t idblk[MAXNINDIR]; 1681426Sroot 1694777Smckusic if (blk != 0) 1705329Smckusic bread(fsbtodb(sblock, blk), (char *)idblk, sblock->fs_bsize); 1714777Smckusic else 17210911Ssam bzero(idblk, sblock->fs_bsize); 1734777Smckusic if (lvl <= 0) { 1745329Smckusic if (*size < NINDIR(sblock) * sblock->fs_bsize) 1755329Smckusic cnt = howmany(*size, sblock->fs_fsize); 1764777Smckusic else 1775329Smckusic cnt = NINDIR(sblock) * sblock->fs_frag; 1785329Smckusic *size -= NINDIR(sblock) * sblock->fs_bsize; 1794777Smckusic blksout(&idblk[0], cnt); 1804777Smckusic return; 1811426Sroot } 1824777Smckusic lvl--; 1835329Smckusic for (i = 0; i < NINDIR(sblock); i++) { 1844777Smckusic dmpindir(idblk[i], lvl, size); 1854777Smckusic if (*size <= 0) 1864777Smckusic return; 1874777Smckusic } 1881426Sroot } 1891426Sroot 1904777Smckusic blksout(blkp, frags) 1914777Smckusic daddr_t *blkp; 1924777Smckusic int frags; 1934777Smckusic { 1945329Smckusic int i, j, count, blks, tbperdb; 1954777Smckusic 1969403Smckusick blks = howmany(frags * sblock->fs_fsize, TP_BSIZE); 1978537Smckusick tbperdb = sblock->fs_bsize / TP_BSIZE; 1984777Smckusic for (i = 0; i < blks; i += TP_NINDIR) { 1994777Smckusic if (i + TP_NINDIR > blks) 2004777Smckusic count = blks; 2014777Smckusic else 2024777Smckusic count = i + TP_NINDIR; 2034777Smckusic for (j = i; j < count; j++) 2045329Smckusic if (blkp[j / tbperdb] != 0) 2054777Smckusic spcl.c_addr[j - i] = 1; 2064777Smckusic else 2074777Smckusic spcl.c_addr[j - i] = 0; 2084777Smckusic spcl.c_count = count - i; 2094777Smckusic spclrec(); 2105329Smckusic for (j = i; j < count; j += tbperdb) 2115329Smckusic if (blkp[j / tbperdb] != 0) 2125329Smckusic if (j + tbperdb <= count) 2135329Smckusic dmpblk(blkp[j / tbperdb], 2145329Smckusic sblock->fs_bsize); 2154777Smckusic else 2165329Smckusic dmpblk(blkp[j / tbperdb], 2174777Smckusic (count - j) * TP_BSIZE); 2184777Smckusic spcl.c_type = TS_ADDR; 2194777Smckusic } 2204777Smckusic } 2214777Smckusic 2221426Sroot bitmap(map, typ) 2235329Smckusic char *map; 2241426Sroot { 22516134Smckusick register i; 2261426Sroot char *cp; 2271426Sroot 2281426Sroot spcl.c_type = typ; 22916134Smckusick spcl.c_count = howmany(msiz * sizeof(map[0]), TP_BSIZE); 2301426Sroot spclrec(); 2315329Smckusic for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE) 2321426Sroot taprec(cp); 2331426Sroot } 2341426Sroot 2351426Sroot spclrec() 2361426Sroot { 2374777Smckusic register int s, i, *ip; 2381426Sroot 2391426Sroot spcl.c_inumber = ino; 2408368Smckusick spcl.c_magic = NFS_MAGIC; 2411426Sroot spcl.c_checksum = 0; 2421426Sroot ip = (int *)&spcl; 2431426Sroot s = 0; 244*24168Smckusick i = sizeof(union u_spcl) / (4*sizeof(int)); 245*24168Smckusick while (--i >= 0) { 246*24168Smckusick s += *ip++; s += *ip++; 247*24168Smckusick s += *ip++; s += *ip++; 248*24168Smckusick } 2491426Sroot spcl.c_checksum = CHECKSUM - s; 2501426Sroot taprec((char *)&spcl); 2511426Sroot } 2521426Sroot 25314928Smckusick dsrch(d, size, filesize) 2544777Smckusic daddr_t d; 25514928Smckusick int size, filesize; 2561426Sroot { 2575942Smckusic register struct direct *dp; 2585942Smckusic long loc; 2595942Smckusic char dblk[MAXBSIZE]; 2601426Sroot 2611426Sroot if(dadded) 2621426Sroot return; 26314928Smckusick if (filesize > size) 26414928Smckusick filesize = size; 26515095Smckusick bread(fsbtodb(sblock, d), dblk, filesize); 26614928Smckusick for (loc = 0; loc < filesize; ) { 2675942Smckusic dp = (struct direct *)(dblk + loc); 26814928Smckusick if (dp->d_reclen == 0) { 26914928Smckusick msg("corrupted directory, inumber %d\n", ino); 2705942Smckusic break; 27114928Smckusick } 2725942Smckusic loc += dp->d_reclen; 2735942Smckusic if(dp->d_ino == 0) 2741426Sroot continue; 2755942Smckusic if(dp->d_name[0] == '.') { 2765942Smckusic if(dp->d_name[1] == '\0') 2771426Sroot continue; 2785942Smckusic if(dp->d_name[1] == '.' && dp->d_name[2] == '\0') 2791426Sroot continue; 2801426Sroot } 2815942Smckusic if(BIT(dp->d_ino, nodmap)) { 2821426Sroot dadded++; 2831426Sroot return; 2841426Sroot } 2855942Smckusic if(BIT(dp->d_ino, dirmap)) 2861426Sroot nsubdir++; 2871426Sroot } 2881426Sroot } 2891426Sroot 2904702Smckusic struct dinode * 2914702Smckusic getino(ino) 2924702Smckusic daddr_t ino; 2934702Smckusic { 2944702Smckusic static daddr_t minino, maxino; 2955329Smckusic static struct dinode itab[MAXINOPB]; 2964702Smckusic 2974702Smckusic if (ino >= minino && ino < maxino) { 2984702Smckusic return (&itab[ino - minino]); 2994702Smckusic } 3005386Smckusic bread(fsbtodb(sblock, itod(sblock, ino)), itab, sblock->fs_bsize); 3015329Smckusic minino = ino - (ino % INOPB(sblock)); 3025329Smckusic maxino = minino + INOPB(sblock); 3034702Smckusic return (&itab[ino - minino]); 3044702Smckusic } 3054702Smckusic 3061426Sroot int breaderrors = 0; 3071426Sroot #define BREADEMAX 32 3081426Sroot 30915095Smckusick bread(da, ba, cnt) 3101426Sroot daddr_t da; 3111426Sroot char *ba; 31215095Smckusick int cnt; 3131426Sroot { 31415095Smckusick int n; 3151426Sroot 31615095Smckusick loop: 3175329Smckusic if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0){ 3181426Sroot msg("bread: lseek fails\n"); 3191426Sroot } 32015095Smckusick n = read(fi, ba, cnt); 32115095Smckusick if (n == cnt) 32215095Smckusick return; 32315095Smckusick if (da + (cnt / DEV_BSIZE) > fsbtodb(sblock, sblock->fs_size)) { 32415095Smckusick /* 32515095Smckusick * Trying to read the final fragment. 32615095Smckusick * 32715095Smckusick * NB - dump only works in TP_BSIZE blocks, hence 32815095Smckusick * rounds DEV_BSIZE fragments up to TP_BSIZE pieces. 32915095Smckusick * It should be smarter about not actually trying to 33015095Smckusick * read more than it can get, but for the time being 33115095Smckusick * we punt and scale back the read only when it gets 33215095Smckusick * us into trouble. (mkm 9/25/83) 33315095Smckusick */ 33415095Smckusick cnt -= DEV_BSIZE; 33515095Smckusick goto loop; 3361426Sroot } 33715095Smckusick msg("(This should not happen)bread from %s [block %d]: count=%d, got=%d\n", 33815095Smckusick disk, da, cnt, n); 33915095Smckusick if (++breaderrors > BREADEMAX){ 34015095Smckusick msg("More than %d block read errors from %d\n", 34115095Smckusick BREADEMAX, disk); 34215095Smckusick broadcast("DUMP IS AILING!\n"); 34315095Smckusick msg("This is an unrecoverable error.\n"); 34415095Smckusick if (!query("Do you want to attempt to continue?")){ 34515095Smckusick dumpabort(); 34615095Smckusick /*NOTREACHED*/ 34715095Smckusick } else 34815095Smckusick breaderrors = 0; 34915095Smckusick } 3501426Sroot } 351