diff --git a/dump_inode.c b/dump_inode.c index 0a19a90..9ff0c06 100644 --- a/dump_inode.c +++ b/dump_inode.c @@ -107,7 +107,7 @@ int main(int argc, char **argv) { usage(); } } - if (!mode || optind + 1 != argc) { + if (!(mode & (MODE_ALL | MODE_INODE)) || optind + 1 != argc) { usage(); } @@ -120,16 +120,16 @@ int main(int argc, char **argv) { // find superblock sblock = xmalloc(SBLOCKSIZE); - int sblock_try[] = SBLOCKSEARCH; + off_t sblock_try[] = SBLOCKSEARCH; int i; for (i = 0; sblock_try[i] != -1; i++) { - ssize_t n = pread(diskfd, sblock, SBLOCKSIZE, (off_t)sblock_try[i]); - if (n == SBLOCKSIZE && - (sblock->fs_magic == FS_UFS1_MAGIC || + xpread(diskfd, sblock, SBLOCKSIZE, sblock_try[i]); + if ((sblock->fs_magic == FS_UFS1_MAGIC || (sblock->fs_magic == FS_UFS2_MAGIC && sblock->fs_sblockloc == sblock_try[i])) && - sblock->fs_bsize <= MAXBSIZE && sblock->fs_bsize >= sizeof(struct fs)) + sblock->fs_bsize <= MAXBSIZE && sblock->fs_bsize >= sizeof(struct fs)) { break; + } } if (sblock_try[i] == -1) { errx(1, "Cannot find filesystem superblock"); @@ -233,26 +233,77 @@ void dump_inode(ino_t inum, union dinode *dp) { DIP(dp, di_mtime), DIP(dp, di_ctime)); } -void dump_dirblk(void *dirblk, size_t size) { - struct direct *d = dirblk; - errx(1, "Not implemented"); +void dump_dirblk(int deleted, void *dirblk, size_t size) { + char *end = (char *)dirblk + size; + for (struct direct *d = dirblk; + (char *)&d->d_name < end && d->d_name + d->d_namlen - 1 < end; + d = (struct direct *)((char *)d + d->d_reclen)) { + char type; + switch (d->d_type) { + case DT_FIFO: + type = 'p'; + break; + case DT_CHR: + type = 'c'; + break; + case DT_DIR: + type = 'd'; + break; + case DT_BLK: + type = 'b'; + break; + case DT_REG: + type = 'f'; + break; + case DT_LNK: + type = 'l'; + break; + case DT_SOCK: + type = 's'; + break; + default: + type = 'u'; + } + 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); + d->d_reclen = MIN(d->d_reclen, end - (char *)d); + d->d_reclen &= ~3; + if (!d->d_reclen) { + if (!deleted) { + warnx("Corrupted directory entry"); + } + return; + } + if (d->d_reclen > DIRSIZ(NEWDIRFMT, d)) { + dump_dirblk(1, (char *)d + DIRSIZ(NEWDIRFMT, d), + d->d_reclen - DIRSIZ(NEWDIRFMT, d)); + } + } } void dump_directory(union dinode *dp) { if ((DIP(dp, di_mode) & IFMT) != IFDIR) { return; } - void *datablock = xmalloc(sblock->fs_bsize); + char *datablock = xmalloc(sblock->fs_bsize); off_t filesize = DIP(dp, di_size); - for (int i = 0; filesize > 0 && i < NDADDR; i++) { - filesize -= sblock->fs_bsize; + for (int i = 0; filesize > 0 && i < NDADDR; + filesize -= sblock->fs_bsize, i++) { if (!DIP(dp, di_db[i])) { continue; } size_t blksize = sblksize(sblock, DIP(dp, di_size), i); daddr_t blkno = fsbtodb(sblock, DIP(dp, di_db[i])); xpread(diskfd, datablock, blksize, blkno * DEV_BSIZE); - dump_dirblk(datablock, blksize); + if (filesize < blksize) { + blksize = filesize; + } + for (size_t j = 0; j < blksize; j += DIRBLKSIZ) { + dump_dirblk(0, datablock + j, MIN(blksize - j, DIRBLKSIZ)); + } } if (filesize > 0) { errx(1, "Indirect blocks not implemented");