📄 ext2fs.c
字号:
/* * Apply the used/unused restriction. */ myflags |= (tsk_getu32(fs->endian, ext2fs->dino_buf->i_ctime) ? TSK_FS_META_FLAG_USED : TSK_FS_META_FLAG_UNUSED); if ((flags & myflags) != myflags) continue; /* If we want only orphans, then check if this * inode is in the seen list */ if ((myflags & TSK_FS_META_FLAG_UNALLOC) && (flags & TSK_FS_META_FLAG_ORPHAN) && (tsk_list_find(fs->list_inum_named, inum))) { continue; } /* * Fill in a file system-independent inode structure and pass control * to the application. */ if (ext2fs_dinode_copy(ext2fs, fs_file->meta)) { tsk_fs_meta_close(fs_file->meta); return 1; } retval = a_action(fs_file, a_ptr); if (retval == TSK_WALK_STOP) { tsk_fs_file_close(fs_file); return 0; } else if (retval == TSK_WALK_ERROR) { tsk_fs_file_close(fs_file); return 1; } } // handle the virtual orphans folder if they asked for it if ((end_inum == TSK_FS_ORPHANDIR_INUM(fs)) && (flags & TSK_FS_META_FLAG_ALLOC) && (flags & TSK_FS_META_FLAG_USED)) { int retval; if (tsk_fs_dir_make_orphan_dir_meta(fs, fs_file->meta)) { tsk_fs_file_close(fs_file); return 1; } /* call action */ retval = a_action(fs_file, a_ptr); if (retval == TSK_WALK_STOP) { tsk_fs_file_close(fs_file); return 0; } else if (retval == TSK_WALK_ERROR) { tsk_fs_file_close(fs_file); return 1; } } /* * Cleanup. */ tsk_fs_file_close(fs_file); return 0;}TSK_FS_BLOCK_FLAG_ENUMext2fs_block_getflags(TSK_FS_INFO * a_fs, TSK_DADDR_T a_addr){ EXT2FS_INFO *ext2fs = (EXT2FS_INFO *) a_fs; int flags; EXT2_GRPNUM_T grp_num; TSK_DADDR_T dbase = 0; /* first block number in group */ TSK_DADDR_T dmin = 0; /* first block after inodes */ // these blocks are not described in the group descriptors if (a_addr < ext2fs->first_data_block) return TSK_FS_BLOCK_FLAG_META | TSK_FS_BLOCK_FLAG_ALLOC; grp_num = ext2_dtog_lcl(a_fs, ext2fs->fs, a_addr); /* Lookup bitmap if not loaded */ if ((ext2fs->bmap_buf == NULL) || (ext2fs->bmap_grp_num != grp_num)) { if (ext2fs_bmap_load(ext2fs, grp_num)) { return 0; } if (tsk_verbose) tsk_fprintf(stderr, "ext2_block_walk: loading group %" PRI_EXT2GRP " dbase %" PRIuDADDR " bmap +%" PRIuDADDR " imap +%" PRIuDADDR " inos +%" PRIuDADDR "..%" PRIuDADDR "\n", grp_num, dbase, (TSK_DADDR_T) tsk_getu32(a_fs->endian, ext2fs->grp_buf->bg_block_bitmap) - dbase, (TSK_DADDR_T) tsk_getu32(a_fs->endian, ext2fs->grp_buf->bg_inode_bitmap) - dbase, (TSK_DADDR_T) tsk_getu32(a_fs->endian, ext2fs->grp_buf->bg_inode_table) - dbase, dmin - 1 - dbase); } /* * Be sure to use the right group descriptor information. XXX There * appears to be an off-by-one discrepancy between bitmap offsets and * disk block numbers. * * Addendum: this offset is controlled by the super block's * s_first_data_block field. */#define INODE_TABLE_SIZE(ext2fs) \ ((tsk_getu32(a_fs->endian, ext2fs->fs->s_inodes_per_group) * ext2fs->inode_size - 1) \ / a_fs->block_size + 1) dbase = ext2_cgbase_lcl(a_fs, ext2fs->fs, grp_num); dmin = tsk_getu32(a_fs->endian, ext2fs->grp_buf->bg_inode_table) + INODE_TABLE_SIZE(ext2fs); /* * Identify meta blocks * (any blocks that can't be allocated for file/directory data). * * XXX With sparse superblock placement, most block groups have the * block and inode bitmaps where one would otherwise find the backup * superblock and the backup group descriptor blocks. The inode * blocks are in the normal place, though. This leaves little gaps * between the bitmaps and the inode table - and ext2fs will use * those blocks for file/directory data blocks. So we must properly * account for those gaps between meta blocks. * * Thus, superblocks and group descriptor blocks are sometimes overlaid * by bitmap blocks. This means that one can still assume that the * locations of superblocks and group descriptor blocks are reserved. * They just happen to be reserved for something else :-) */ flags = (isset(ext2fs->bmap_buf, a_addr - dbase) ? TSK_FS_BLOCK_FLAG_ALLOC : TSK_FS_BLOCK_FLAG_UNALLOC); if ((a_addr >= dbase && a_addr < tsk_getu32(a_fs->endian, ext2fs->grp_buf->bg_block_bitmap)) || (a_addr == tsk_getu32(a_fs->endian, ext2fs->grp_buf->bg_block_bitmap)) || (a_addr == tsk_getu32(a_fs->endian, ext2fs->grp_buf->bg_inode_bitmap)) || (a_addr >= tsk_getu32(a_fs->endian, ext2fs->grp_buf->bg_inode_table) && a_addr < dmin)) flags |= TSK_FS_BLOCK_FLAG_META; else flags |= TSK_FS_BLOCK_FLAG_CONT; return flags;}/* ext2fs_block_walk - block iterator * * flags: TSK_FS_BLOCK_FLAG_ALLOC, TSK_FS_BLOCK_FLAG_UNALLOC, TSK_FS_BLOCK_FLAG_CONT, * TSK_FS_BLOCK_FLAG_META * * Return 1 on error and 0 on success*/uint8_text2fs_block_walk(TSK_FS_INFO * a_fs, TSK_DADDR_T a_start_blk, TSK_DADDR_T a_end_blk, TSK_FS_BLOCK_WALK_FLAG_ENUM a_flags, TSK_FS_BLOCK_WALK_CB a_action, void *a_ptr){ char *myname = "extXfs_block_walk"; TSK_FS_BLOCK *fs_block; TSK_DADDR_T addr; // clean up any error messages that are lying around tsk_error_reset(); /* * Sanity checks. */ if (a_start_blk < a_fs->first_block || a_start_blk > a_fs->last_block) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_WALK_RNG; snprintf(tsk_errstr, TSK_ERRSTR_L, "%s: start block: %" PRIuDADDR, myname, a_start_blk); return 1; } if (a_end_blk < a_fs->first_block || a_end_blk > a_fs->last_block || a_end_blk < a_start_blk) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_WALK_RNG; snprintf(tsk_errstr, TSK_ERRSTR_L, "%s: end block: %" PRIuDADDR, myname, a_end_blk); return 1; } /* Sanity check on a_flags -- make sure at least one ALLOC is set */ if (((a_flags & TSK_FS_BLOCK_WALK_FLAG_ALLOC) == 0) && ((a_flags & TSK_FS_BLOCK_WALK_FLAG_UNALLOC) == 0)) { a_flags |= (TSK_FS_BLOCK_WALK_FLAG_ALLOC | TSK_FS_BLOCK_WALK_FLAG_UNALLOC); } if (((a_flags & TSK_FS_BLOCK_WALK_FLAG_META) == 0) && ((a_flags & TSK_FS_BLOCK_WALK_FLAG_CONT) == 0)) { a_flags |= (TSK_FS_BLOCK_WALK_FLAG_CONT | TSK_FS_BLOCK_WALK_FLAG_META); } if ((fs_block = tsk_fs_block_alloc(a_fs)) == NULL) { return 1; } /* * Iterate. This is not as tricky as it could be, because the free list * map covers the entire disk partition, including blocks occupied by * group descriptor blocks, bit maps, and other non-data blocks. */ for (addr = a_start_blk; addr <= a_end_blk; addr++) { int retval; int myflags; myflags = ext2fs_block_getflags(a_fs, addr); // test if we should call the callback with this one if ((myflags & TSK_FS_BLOCK_FLAG_META) && (!(a_flags & TSK_FS_BLOCK_WALK_FLAG_META))) continue; else if ((myflags & TSK_FS_BLOCK_FLAG_CONT) && (!(a_flags & TSK_FS_BLOCK_WALK_FLAG_CONT))) continue; else if ((myflags & TSK_FS_BLOCK_FLAG_ALLOC) && (!(a_flags & TSK_FS_BLOCK_WALK_FLAG_ALLOC))) continue; else if ((myflags & TSK_FS_BLOCK_FLAG_UNALLOC) && (!(a_flags & TSK_FS_BLOCK_WALK_FLAG_UNALLOC))) continue; if (tsk_fs_block_get(a_fs, fs_block, addr) == NULL) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "ext2fs_block_walk: block %" PRIuDADDR, addr); tsk_fs_block_free(fs_block); return 1; } retval = a_action(fs_block, a_ptr); if (retval == TSK_WALK_STOP) { break; } else if (retval == TSK_WALK_ERROR) { tsk_fs_block_free(fs_block); return 1; } } /* * Cleanup. */ tsk_fs_block_free(fs_block); return 0;}static uint8_text2fs_fscheck(TSK_FS_INFO * fs, FILE * hFile){ tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNSUPFUNC; snprintf(tsk_errstr, TSK_ERRSTR_L, "fscheck not implemented yet for Ext3"); return 1;}/** * Print details about the file system to a file handle. * * @param fs File system to print details on * @param hFile File handle to print text to * * @returns 1 on error and 0 on success */static uint8_text2fs_fsstat(TSK_FS_INFO * fs, FILE * hFile){ unsigned int i; EXT2FS_INFO *ext2fs = (EXT2FS_INFO *) fs; ext2fs_sb *sb = ext2fs->fs; int ibpg; time_t tmptime; // clean up any error messages that are lying around tsk_error_reset(); tsk_fprintf(hFile, "FILE SYSTEM INFORMATION\n"); tsk_fprintf(hFile, "--------------------------------------------\n"); tsk_fprintf(hFile, "File System Type: %s\n", (fs->ftype == TSK_FS_TYPE_EXT3) ? "Ext3" : "Ext2"); tsk_fprintf(hFile, "Volume Name: %s\n", sb->s_volume_name); tsk_fprintf(hFile, "Volume ID: %" PRIx64 "%" PRIx64 "\n", tsk_getu64(fs->endian, &sb->s_uuid[8]), tsk_getu64(fs->endian, &sb->s_uuid[0])); tmptime = tsk_getu32(fs->endian, sb->s_wtime); tsk_fprintf(hFile, "\nLast Written at: %s", (tmptime > 0) ? asctime(localtime(&tmptime)) : "empty"); tmptime = tsk_getu32(fs->endian, sb->s_lastcheck); tsk_fprintf(hFile, "Last Checked at: %s", (tmptime > 0) ? asctime(localtime(&tmptime)) : "empty"); tmptime = tsk_getu32(fs->endian, sb->s_mtime); tsk_fprintf(hFile, "\nLast Mounted at: %s", (tmptime > 0) ? asctime(localtime(&tmptime)) : "empty"); /* State of the file system */ if (tsk_getu16(fs->endian, sb->s_state) & EXT2FS_STATE_VALID) tsk_fprintf(hFile, "Unmounted properly\n"); else tsk_fprintf(hFile, "Unmounted Improperly\n"); if (sb->s_last_mounted != '\0') tsk_fprintf(hFile, "Last mounted on: %s\n", sb->s_last_mounted); tsk_fprintf(hFile, "\nSource OS: "); switch (tsk_getu32(fs->endian, sb->s_creator_os)) { case EXT2FS_OS_LINUX: tsk_fprintf(hFile, "Linux\n"); break; case EXT2FS_OS_HURD: tsk_fprintf(hFile, "HURD\n"); break; case EXT2FS_OS_MASIX: tsk_fprintf(hFile, "MASIX\n"); break; case EXT2FS_OS_FREEBSD: tsk_fprintf(hFile, "FreeBSD\n"); break; case EXT2FS_OS_LITES: tsk_fprintf(hFile, "LITES\n"); break; default: tsk_fprintf(hFile, "%" PRIx32 "\n", tsk_getu32(fs->endian, sb->s_creator_os)); break; } if (tsk_getu32(fs->endian, sb->s_rev_level) == EXT2FS_REV_ORIG) tsk_fprintf(hFile, "Static Structure\n"); else tsk_fprintf(hFile, "Dynamic Structure\n"); /* add features */ if (tsk_getu32(fs->endian, sb->s_feature_compat)) { tsk_fprintf(hFile, "Compat Features: "); if (tsk_getu32(fs->endian, sb->s_feature_compat) & EXT2FS_FEATURE_COMPAT_DIR_PREALLOC) tsk_fprintf(hFile, "Dir Prealloc, "); if (tsk_getu32(fs->endian, sb->s_feature_compat) & EXT2FS_FEATURE_COMPAT_IMAGIC_INODES) tsk_fprintf(hFile, "iMagic inodes, "); if (tsk_getu32(fs->endian, sb->s_feature_compat) & EXT2FS_FEATURE_COMPAT_HAS_JOURNAL) tsk_fprintf(hFile, "Journal, "); if (tsk_getu32(fs->endian, sb->s_feature_compat) & EXT2FS_FEATURE_COMPAT_EXT_ATTR) tsk_fprintf(hFile, "Ext Attributes, "); if (tsk_getu32(fs->endian, sb->s_feature_compat) & EXT2FS_FEATURE_COMPAT_RESIZE_INO) tsk_fprintf(hFile, "Resize Inode, "); if (tsk_getu32(fs->endian, sb->s_feature_compat) & EXT2FS_FEATURE_COMPAT_DIR_INDEX) tsk_fprintf(hFile, "Dir Index"); tsk_fprintf(hFile, "\n"); } if (tsk_getu32(fs->endian, sb->s_feature_incompat)) { tsk_fprintf(hFile, "InCompat Features: "); if (tsk_getu32(fs->endian, sb->s_feature_incompat) & EXT2FS_FEATURE_INCOMPAT_COMPRESSION) tsk_fprintf(hFile, "Compression, "); if (tsk_getu32(fs->endian, sb->s_feature_incompat) & EXT2FS_FEATURE_INCOMPAT_FILETYPE) tsk_fprintf(hFile, "Filetype, "); if (tsk_getu32(fs->endian, sb->s_feature_incompat) & EXT2FS_FEATURE_INCOMPAT_RECOVER) tsk_fprintf(hFile, "Needs Recovery, "); if (tsk_getu32(fs->endian, sb->s_feature_incompat) &
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -