diff options
Diffstat (limited to 'ufs-fsck/inode.c')
-rw-r--r-- | ufs-fsck/inode.c | 55 |
1 files changed, 49 insertions, 6 deletions
diff --git a/ufs-fsck/inode.c b/ufs-fsck/inode.c index 44b79de3..e8924e1a 100644 --- a/ufs-fsck/inode.c +++ b/ufs-fsck/inode.c @@ -20,12 +20,43 @@ static void inode_iterate (struct dinode *dp, - int (*fn (daddr_t, int)), + int (*fn) (daddr_t, int), int doaddrblocks) { mode_t mode = dp->di_model & IFMT; int nb, maxb; + /* Call FN for iblock IBLOCK of level LEVEL and recurse down + the indirect block pointers. */ + int + scaniblock (daddr_t iblock, int level) + { + int cont; + daddr_t ptrs[NIADDR(sblock)]; + int i; + + if (doaddrblocks) + { + cont = (*fn)(iblock, sblock->fs_frag); + if (cont == RET_STOP) + return RET_STOP; + else if (cont == RET_BAD) + return RET_GOOD; + } + + readblock (fsbtodb (iblock), buf, sblock->fs_bsize); + for (i = 0; i < NIADDR (sblock); i++) + { + if (level == 0) + cont = (*fn)(ptrs[i], sblock->fs_frag); + else + cont = scaniblock (ptrs[i], level - 1); + if (cont == RET_STOP) + return RET_STOP; + } + return RET_GOOD; + } + if (mode == IFBLK || mode == IFCHR || (mode == IFLNK && sblock->fs_maxsymlinklen != -1 && (dp->di_size < sblock->fs_maxsymlinklen @@ -44,17 +75,29 @@ inode_iterate (struct dinode *dp, else nfrags = sblock->fs_frag; - if (dp->di_db[nb] != 0) - if ((*fn)(dp->di_db[nb], nfrags) != RET_GOOD) - return; + if (dp->di_db[nb] && (*fn)(dp->di_db[nb], nfrags) != RET_GOOD) + return; } for (nb = 0; nb < NIADDR; nb++) - if (scaniblock (dp->di_db[nb], nb) != RET_GOOD) + if (dp->di_ib[nb] && scaniblock (dp->di_ib[nb], nb) != RET_GOOD) return; if (doaddrblocks && dp->di_trans) (*fn)(dp->di_trans, sblock->fs_frag); } - +void +datablocks_iterate (struct dinode *dp, + int (*fn) (daddr_t, int)) +{ + inode_iterate (dp, fn, 0); +} + +void +allblock_iterate (struct dinode *dp, + int (*fn) (daddr_t, int)) +{ + inode_iterate (dp, fn, 1); +} + |