diff --git a/dump_inode.c b/dump_inode.c index 9ff0c06..0b2bb3f 100644 --- a/dump_inode.c +++ b/dump_inode.c @@ -267,8 +267,8 @@ void dump_dirblk(int deleted, void *dirblk, size_t size) { char name[MAXNAMLEN + 1]; memcpy(name, d->d_name, d->d_namlen); name[d->d_namlen] = '\0'; - printf("deleted:%d inode:%" PRIu32 " type:%c name:%s\n", deleted, d->d_ino, - type, name); + printf("deleted:%d inode:%" PRIu32 " type:%c name:%s\n", + deleted || !d->d_ino, d->d_ino, type, name); d->d_reclen = MIN(d->d_reclen, end - (char *)d); d->d_reclen &= ~3; if (!d->d_reclen) { @@ -284,6 +284,54 @@ void dump_dirblk(int deleted, void *dirblk, size_t size) { } } +void dump_directory_indirect(union dinode *dp, void *indirblock, int level, off_t *filesize) { + void *datablock = xmalloc(sblock->fs_bsize); + if (!level) { + for (int i = 0; *filesize > 0 && i < NINDIR(sblock); + *filesize -= sblock->fs_bsize, i++) { + daddr_t fsblkno; + if (sblock->fs_magic == FS_UFS1_MAGIC) { + fsblkno = ((uint32_t *)indirblock)[i]; + } else { + fsblkno = ((uint64_t *)indirblock)[i]; + } + if (!fsblkno) { + continue; + } + size_t blksize = sblock->fs_bsize; + daddr_t blkno = fsbtodb(sblock, fsblkno); + xpread(diskfd, datablock, blksize, blkno * DEV_BSIZE); + if (*filesize < blksize) { + blksize = *filesize; + } + for (size_t j = 0; j < blksize; j += DIRBLKSIZ) { + dump_dirblk(0, datablock + j, MIN(blksize - j, DIRBLKSIZ)); + } + } + } else { + for (int i = 0; *filesize > 0 && i < NINDIR(sblock); i++) { + daddr_t fsblkno; + if (sblock->fs_magic == FS_UFS1_MAGIC) { + fsblkno = ((uint32_t *)indirblock)[i]; + } else { + fsblkno = ((uint64_t *)indirblock)[i]; + } + if (!fsblkno) { + size_t gapsize = NINDIR(sblock) * sblock->fs_bsize; + for (int j = 0; j < i; j++) { + gapsize *= NINDIR(sblock); + } + *filesize -= gapsize; + continue; + } + daddr_t blkno = fsbtodb(sblock, fsblkno); + xpread(diskfd, datablock, sblock->fs_bsize, blkno * DEV_BSIZE); + dump_directory_indirect(dp, datablock, level - 1, filesize); + } + } + free(datablock); +} + void dump_directory(union dinode *dp) { if ((DIP(dp, di_mode) & IFMT) != IFDIR) { return; @@ -305,8 +353,18 @@ void dump_directory(union dinode *dp) { dump_dirblk(0, datablock + j, MIN(blksize - j, DIRBLKSIZ)); } } - if (filesize > 0) { - errx(1, "Indirect blocks not implemented"); + for (int i = 0; filesize > 0 && i < NIADDR; i++) { + if (!DIP(dp, di_ib[i])) { + size_t gapsize = NINDIR(sblock) * sblock->fs_bsize; + for (int j = 0; j < i; j++) { + gapsize *= NINDIR(sblock); + } + filesize -= gapsize; + continue; + } + daddr_t blkno = fsbtodb(sblock, DIP(dp, di_ib[i])); + xpread(diskfd, datablock, sblock->fs_bsize, blkno * DEV_BSIZE); + dump_directory_indirect(dp, datablock, i, &filesize); } free(datablock); }