1 static char *sccsid = "@(#)traverse.c 1.7 (Berkeley) 03/23/82"; 2 3 #include "dump.h" 4 #include <ndir.h> 5 6 pass(fn, map) 7 int (*fn)(); 8 char *map; 9 { 10 struct dinode *dp; 11 int bits; 12 ino_t maxino; 13 14 maxino = sblock->fs_ipg * sblock->fs_ncg - 1; 15 for (ino = 0; ino < maxino; ) { 16 if((ino % NBBY) == 0) { 17 bits = ~0; 18 if(map != NULL) 19 bits = *map++; 20 } 21 ino++; 22 if(bits & 1) { 23 dp = getino(ino); 24 (*fn)(dp); 25 } 26 bits >>= 1; 27 } 28 } 29 30 mark(ip) 31 struct dinode *ip; 32 { 33 register f; 34 35 f = ip->di_mode & IFMT; 36 if(f == 0) 37 return; 38 BIS(ino, clrmap); 39 if(f == IFDIR) 40 BIS(ino, dirmap); 41 if ((ip->di_mtime >= spcl.c_ddate || ip->di_ctime >= spcl.c_ddate) && 42 !BIT(ino, nodmap)) { 43 BIS(ino, nodmap); 44 if (f != IFREG && f != IFDIR && f != IFLNK) { 45 esize += 1; 46 return; 47 } 48 est(ip); 49 } 50 } 51 52 add(ip) 53 register struct dinode *ip; 54 { 55 register int i; 56 57 if(BIT(ino, nodmap)) 58 return; 59 nsubdir = 0; 60 dadded = 0; 61 for (i = 0; i < NDADDR; i++) { 62 if (ip->di_db[i] != 0) 63 dsrch(ip->di_db[i], dblksize(sblock, ip, i)); 64 } 65 for (i = 0; i < NIADDR; i++) { 66 if (ip->di_ib[i] != 0) 67 indir(ip->di_ib[i], i); 68 } 69 if(dadded) { 70 nadded++; 71 if (!BIT(ino, nodmap)) { 72 BIS(ino, nodmap); 73 est(ip); 74 } 75 } 76 if(nsubdir == 0) 77 if(!BIT(ino, nodmap)) 78 BIC(ino, dirmap); 79 } 80 81 indir(d, n) 82 daddr_t d; 83 int n; 84 { 85 register i; 86 daddr_t idblk[MAXNINDIR]; 87 88 bread(fsbtodb(sblock, d), (char *)idblk, sblock->fs_bsize); 89 if(n <= 0) { 90 for(i=0; i < NINDIR(sblock); i++) { 91 d = idblk[i]; 92 if(d != 0) 93 dsrch(d, sblock->fs_bsize); 94 } 95 } else { 96 n--; 97 for(i=0; i < NINDIR(sblock); i++) { 98 d = idblk[i]; 99 if(d != 0) 100 indir(d, n); 101 } 102 } 103 } 104 105 dump(ip) 106 struct dinode *ip; 107 { 108 register int i; 109 long size; 110 111 if(newtape) { 112 newtape = 0; 113 bitmap(nodmap, TS_BITS); 114 } 115 BIC(ino, nodmap); 116 spcl.c_dinode = *ip; 117 spcl.c_type = TS_INODE; 118 spcl.c_count = 0; 119 i = ip->di_mode & IFMT; 120 if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) { 121 spclrec(); 122 return; 123 } 124 if (ip->di_size > NDADDR * sblock->fs_bsize) 125 i = NDADDR * sblock->fs_frag; 126 else 127 i = howmany(ip->di_size, sblock->fs_fsize); 128 blksout(&ip->di_db[0], i); 129 size = ip->di_size - NDADDR * sblock->fs_bsize; 130 if (size <= 0) 131 return; 132 for (i = 0; i < NIADDR; i++) { 133 dmpindir(ip->di_ib[i], i, &size); 134 if (size <= 0) 135 return; 136 } 137 } 138 139 dmpindir(blk, lvl, size) 140 daddr_t blk; 141 int lvl; 142 long *size; 143 { 144 int i, cnt; 145 daddr_t idblk[MAXNINDIR]; 146 147 if (blk != 0) 148 bread(fsbtodb(sblock, blk), (char *)idblk, sblock->fs_bsize); 149 else 150 blkclr(idblk, sblock->fs_bsize); 151 if (lvl <= 0) { 152 if (*size < NINDIR(sblock) * sblock->fs_bsize) 153 cnt = howmany(*size, sblock->fs_fsize); 154 else 155 cnt = NINDIR(sblock) * sblock->fs_frag; 156 *size -= NINDIR(sblock) * sblock->fs_bsize; 157 blksout(&idblk[0], cnt); 158 return; 159 } 160 lvl--; 161 for (i = 0; i < NINDIR(sblock); i++) { 162 dmpindir(idblk[i], lvl, size); 163 if (*size <= 0) 164 return; 165 } 166 } 167 168 blksout(blkp, frags) 169 daddr_t *blkp; 170 int frags; 171 { 172 int i, j, count, blks, tbperdb; 173 174 blks = frags * BLKING(sblock); 175 tbperdb = BLKING(sblock) * sblock->fs_frag; 176 for (i = 0; i < blks; i += TP_NINDIR) { 177 if (i + TP_NINDIR > blks) 178 count = blks; 179 else 180 count = i + TP_NINDIR; 181 for (j = i; j < count; j++) 182 if (blkp[j / tbperdb] != 0) 183 spcl.c_addr[j - i] = 1; 184 else 185 spcl.c_addr[j - i] = 0; 186 spcl.c_count = count - i; 187 spclrec(); 188 for (j = i; j < count; j += tbperdb) 189 if (blkp[j / tbperdb] != 0) 190 if (j + tbperdb <= count) 191 dmpblk(blkp[j / tbperdb], 192 sblock->fs_bsize); 193 else 194 dmpblk(blkp[j / tbperdb], 195 (count - j) * TP_BSIZE); 196 spcl.c_type = TS_ADDR; 197 } 198 } 199 200 bitmap(map, typ) 201 char *map; 202 { 203 register i, n; 204 char *cp; 205 206 n = -1; 207 for (i = 0; i < msiz; i++) 208 if(map[i]) 209 n = i; 210 if (n < 0) 211 return; 212 n++; 213 spcl.c_type = typ; 214 spcl.c_count = howmany(n * sizeof(map[0]), TP_BSIZE); 215 spclrec(); 216 for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE) 217 taprec(cp); 218 } 219 220 spclrec() 221 { 222 register int s, i, *ip; 223 224 spcl.c_inumber = ino; 225 spcl.c_magic = MAGIC; 226 spcl.c_checksum = 0; 227 ip = (int *)&spcl; 228 s = 0; 229 for(i = 0; i < sizeof(union u_spcl)/sizeof(int); i++) 230 s += *ip++; 231 spcl.c_checksum = CHECKSUM - s; 232 taprec((char *)&spcl); 233 } 234 235 dsrch(d, size) 236 daddr_t d; 237 int size; 238 { 239 register struct direct *dp; 240 long loc; 241 char dblk[MAXBSIZE]; 242 243 if(dadded) 244 return; 245 bread(fsbtodb(sblock, d), dblk, size); 246 for (loc = 0; loc < size; ) { 247 dp = (struct direct *)(dblk + loc); 248 if (dp->d_reclen == 0) 249 break; 250 loc += dp->d_reclen; 251 if(dp->d_ino == 0) 252 continue; 253 if(dp->d_name[0] == '.') { 254 if(dp->d_name[1] == '\0') 255 continue; 256 if(dp->d_name[1] == '.' && dp->d_name[2] == '\0') 257 continue; 258 } 259 if(BIT(dp->d_ino, nodmap)) { 260 dadded++; 261 return; 262 } 263 if(BIT(dp->d_ino, dirmap)) 264 nsubdir++; 265 } 266 } 267 268 struct dinode * 269 getino(ino) 270 daddr_t ino; 271 { 272 static daddr_t minino, maxino; 273 static struct dinode itab[MAXINOPB]; 274 275 if (ino >= minino && ino < maxino) { 276 return (&itab[ino - minino]); 277 } 278 bread(fsbtodb(sblock, itod(sblock, ino)), itab, sblock->fs_bsize); 279 minino = ino - (ino % INOPB(sblock)); 280 maxino = minino + INOPB(sblock); 281 return (&itab[ino - minino]); 282 } 283 284 int breaderrors = 0; 285 #define BREADEMAX 32 286 287 bread(da, ba, c) 288 daddr_t da; 289 char *ba; 290 int c; 291 { 292 register n; 293 register regc; 294 295 if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0){ 296 msg("bread: lseek fails\n"); 297 } 298 regc = c; /* put c someplace safe; it gets clobbered */ 299 n = read(fi, ba, c); 300 if (n != c || regc != c) { 301 msg("(This should not happen)bread from %s [block %d]: c=0x%x, regc=0x%x, &c=0x%x, n=0x%x\n", 302 disk, da, c, regc, &c, n); 303 #ifdef ERNIE 304 msg("Notify Robert Henry of this error.\n"); 305 #endif 306 if (++breaderrors > BREADEMAX){ 307 msg("More than %d block read errors from %d\n", 308 BREADEMAX, disk); 309 broadcast("DUMP IS AILING!\n"); 310 msg("This is an unrecoverable error.\n"); 311 if (!query("Do you want to attempt to continue?")){ 312 dumpabort(); 313 /*NOTREACHED*/ 314 } else 315 breaderrors = 0; 316 } 317 } 318 } 319 320 blkclr(cp, size) 321 char *cp; 322 long size; 323 { 324 asm("movc5 $0,(r0),$0,8(ap),*4(ap)"); 325 } 326