1*22041Sdist /* 2*22041Sdist * Copyright (c) 1980 Regents of the University of California. 3*22041Sdist * All rights reserved. The Berkeley software License Agreement 4*22041Sdist * specifies the terms and conditions for redistribution. 5*22041Sdist */ 65329Smckusic 7*22041Sdist #ifndef lint 8*22041Sdist static char sccsid[] = "@(#)traverse.c 5.1 (Berkeley) 06/05/85"; 9*22041Sdist #endif not lint 10*22041Sdist 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; 2444777Smckusic for(i = 0; i < sizeof(union u_spcl)/sizeof(int); i++) 2451426Sroot s += *ip++; 2461426Sroot spcl.c_checksum = CHECKSUM - s; 2471426Sroot taprec((char *)&spcl); 2481426Sroot } 2491426Sroot 25014928Smckusick dsrch(d, size, filesize) 2514777Smckusic daddr_t d; 25214928Smckusick int size, filesize; 2531426Sroot { 2545942Smckusic register struct direct *dp; 2555942Smckusic long loc; 2565942Smckusic char dblk[MAXBSIZE]; 2571426Sroot 2581426Sroot if(dadded) 2591426Sroot return; 26014928Smckusick if (filesize > size) 26114928Smckusick filesize = size; 26215095Smckusick bread(fsbtodb(sblock, d), dblk, filesize); 26314928Smckusick for (loc = 0; loc < filesize; ) { 2645942Smckusic dp = (struct direct *)(dblk + loc); 26514928Smckusick if (dp->d_reclen == 0) { 26614928Smckusick msg("corrupted directory, inumber %d\n", ino); 2675942Smckusic break; 26814928Smckusick } 2695942Smckusic loc += dp->d_reclen; 2705942Smckusic if(dp->d_ino == 0) 2711426Sroot continue; 2725942Smckusic if(dp->d_name[0] == '.') { 2735942Smckusic if(dp->d_name[1] == '\0') 2741426Sroot continue; 2755942Smckusic if(dp->d_name[1] == '.' && dp->d_name[2] == '\0') 2761426Sroot continue; 2771426Sroot } 2785942Smckusic if(BIT(dp->d_ino, nodmap)) { 2791426Sroot dadded++; 2801426Sroot return; 2811426Sroot } 2825942Smckusic if(BIT(dp->d_ino, dirmap)) 2831426Sroot nsubdir++; 2841426Sroot } 2851426Sroot } 2861426Sroot 2874702Smckusic struct dinode * 2884702Smckusic getino(ino) 2894702Smckusic daddr_t ino; 2904702Smckusic { 2914702Smckusic static daddr_t minino, maxino; 2925329Smckusic static struct dinode itab[MAXINOPB]; 2934702Smckusic 2944702Smckusic if (ino >= minino && ino < maxino) { 2954702Smckusic return (&itab[ino - minino]); 2964702Smckusic } 2975386Smckusic bread(fsbtodb(sblock, itod(sblock, ino)), itab, sblock->fs_bsize); 2985329Smckusic minino = ino - (ino % INOPB(sblock)); 2995329Smckusic maxino = minino + INOPB(sblock); 3004702Smckusic return (&itab[ino - minino]); 3014702Smckusic } 3024702Smckusic 3031426Sroot int breaderrors = 0; 3041426Sroot #define BREADEMAX 32 3051426Sroot 30615095Smckusick bread(da, ba, cnt) 3071426Sroot daddr_t da; 3081426Sroot char *ba; 30915095Smckusick int cnt; 3101426Sroot { 31115095Smckusick int n; 3121426Sroot 31315095Smckusick loop: 3145329Smckusic if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0){ 3151426Sroot msg("bread: lseek fails\n"); 3161426Sroot } 31715095Smckusick n = read(fi, ba, cnt); 31815095Smckusick if (n == cnt) 31915095Smckusick return; 32015095Smckusick if (da + (cnt / DEV_BSIZE) > fsbtodb(sblock, sblock->fs_size)) { 32115095Smckusick /* 32215095Smckusick * Trying to read the final fragment. 32315095Smckusick * 32415095Smckusick * NB - dump only works in TP_BSIZE blocks, hence 32515095Smckusick * rounds DEV_BSIZE fragments up to TP_BSIZE pieces. 32615095Smckusick * It should be smarter about not actually trying to 32715095Smckusick * read more than it can get, but for the time being 32815095Smckusick * we punt and scale back the read only when it gets 32915095Smckusick * us into trouble. (mkm 9/25/83) 33015095Smckusick */ 33115095Smckusick cnt -= DEV_BSIZE; 33215095Smckusick goto loop; 3331426Sroot } 33415095Smckusick msg("(This should not happen)bread from %s [block %d]: count=%d, got=%d\n", 33515095Smckusick disk, da, cnt, n); 33615095Smckusick if (++breaderrors > BREADEMAX){ 33715095Smckusick msg("More than %d block read errors from %d\n", 33815095Smckusick BREADEMAX, disk); 33915095Smckusick broadcast("DUMP IS AILING!\n"); 34015095Smckusick msg("This is an unrecoverable error.\n"); 34115095Smckusick if (!query("Do you want to attempt to continue?")){ 34215095Smckusick dumpabort(); 34315095Smckusick /*NOTREACHED*/ 34415095Smckusick } else 34515095Smckusick breaderrors = 0; 34615095Smckusick } 3471426Sroot } 348