⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ffs.c

📁 linux下开发的针对所有磁盘的数据恢复的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
 * * INODE WALKING * **************************************************************************//* ffs_inode_walk - inode iterator  * * flags used: TSK_FS_META_FLAG_USED, TSK_FS_META_FLAG_UNUSED,  *  TSK_FS_META_FLAG_ALLOC, TSK_FS_META_FLAG_UNALLOC, TSK_FS_META_FLAG_ORPHAN * *  return 1 on error and 0 on success */uint8_tffs_inode_walk(TSK_FS_INFO * fs, TSK_INUM_T start_inum,    TSK_INUM_T end_inum, TSK_FS_META_FLAG_ENUM a_flags,    TSK_FS_META_WALK_CB action, void *ptr){    char *myname = "ffs_inode_walk";    FFS_INFO *ffs = (FFS_INFO *) fs;    FFS_GRPNUM_T grp_num;    ffs_cgd *cg = NULL;    TSK_INUM_T inum;    unsigned char *inosused = NULL;    TSK_FS_FILE *fs_file;    int myflags;    TSK_INUM_T ibase = 0;    TSK_INUM_T end_inum_tmp;    // clean up any error messages that are lying around    tsk_error_reset();    /*     * Sanity checks.     */    if (start_inum < fs->first_inum || start_inum > fs->last_inum) {        tsk_error_reset();        tsk_errno = TSK_ERR_FS_WALK_RNG;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "%s: Start inode: %" PRIuINUM "", myname, start_inum);        return 1;    }    else if (end_inum < fs->first_inum || end_inum > fs->last_inum        || end_inum < start_inum) {        tsk_error_reset();        tsk_errno = TSK_ERR_FS_WALK_RNG;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "%s: End inode: %" PRIuINUM "", myname, end_inum);        return 1;    }    /* If ORPHAN is wanted, then make sure that the flags are correct */    if (a_flags & TSK_FS_META_FLAG_ORPHAN) {        a_flags |= TSK_FS_META_FLAG_UNALLOC;        a_flags &= ~TSK_FS_META_FLAG_ALLOC;        a_flags |= TSK_FS_META_FLAG_USED;        a_flags &= ~TSK_FS_META_FLAG_UNUSED;    }    else {        if (((a_flags & TSK_FS_META_FLAG_ALLOC) == 0) &&            ((a_flags & TSK_FS_META_FLAG_UNALLOC) == 0)) {            a_flags |= (TSK_FS_META_FLAG_ALLOC | TSK_FS_META_FLAG_UNALLOC);        }        /* If neither of the USED or UNUSED flags are set, then set them         * both         */        if (((a_flags & TSK_FS_META_FLAG_USED) == 0) &&            ((a_flags & TSK_FS_META_FLAG_UNUSED) == 0)) {            a_flags |= (TSK_FS_META_FLAG_USED | TSK_FS_META_FLAG_UNUSED);        }    }    /* If we are looking for orphan files and have not yet filled     * in the list of unalloc inodes that are pointed to, then fill     * in the list     * */    if ((a_flags & TSK_FS_META_FLAG_ORPHAN)        && (fs->list_inum_named == NULL)) {        if (tsk_fs_dir_load_inum_named(fs) != TSK_OK) {            strncat(tsk_errstr2,                " - ffs_inode_walk: identifying inodes allocated by file names",                TSK_ERRSTR_L);            return 1;        }    }    if ((fs_file = tsk_fs_file_alloc(fs)) == NULL)        return 1;    if ((fs_file->meta = tsk_fs_meta_alloc(FFS_FILE_CONTENT_LEN)) == NULL)        return 1;    // we need to handle fs->last_inum specially because it is for the     // virtual ORPHANS directory.  Handle it outside of the loop.    if (end_inum == TSK_FS_ORPHANDIR_INUM(fs))        end_inum_tmp = end_inum - 1;    else        end_inum_tmp = end_inum;    /*     * Iterate. This is easy because inode numbers are contiguous, unlike     * data blocks which are interleaved with cylinder group blocks.     */    for (inum = start_inum; inum <= end_inum_tmp; inum++) {        int retval;        /*         * Be sure to use the proper cylinder group data.         */        grp_num = itog_lcl(fs, ffs->fs.sb1, inum);        if ((ffs->grp_buf == NULL) || (grp_num != ffs->grp_num)) {            if (ffs_group_load(ffs, grp_num))                return 1;            cg = NULL;        }        /* Load up the cached one if the needed one was already loaded or if a new was just loaded */        if (cg == NULL) {            cg = (ffs_cgd *) ffs->grp_buf;            inosused = (unsigned char *) cg_inosused_lcl(fs, cg);            ibase =                grp_num * tsk_gets32(fs->endian,                ffs->fs.sb1->cg_inode_num);        }        /*         * Apply the allocated/unallocated restriction.         */        myflags = (isset(inosused, inum - ibase) ?            TSK_FS_META_FLAG_ALLOC : TSK_FS_META_FLAG_UNALLOC);        if ((a_flags & myflags) != myflags)            continue;        if (ffs_dinode_load(ffs, inum)) {            tsk_fs_file_close(fs_file);            return 1;        }        if ((fs->ftype == TSK_FS_TYPE_FFS1)            || (fs->ftype == TSK_FS_TYPE_FFS1B)) {            /* both inode forms are the same for the required fields */            ffs_inode1 *in1 = (ffs_inode1 *) ffs->dino_buf;            /*             * Apply the used/unused restriction.             */            myflags |= (tsk_gets32(fs->endian, in1->di_ctime) ?                TSK_FS_META_FLAG_USED : TSK_FS_META_FLAG_UNUSED);            if ((a_flags & myflags) != myflags)                continue;        }        else {            ffs_inode2 *in2 = (ffs_inode2 *) ffs->dino_buf;            /*             * Apply the used/unused restriction.             */            myflags |= (tsk_gets64(fs->endian, in2->di_ctime) ?                TSK_FS_META_FLAG_USED : TSK_FS_META_FLAG_UNUSED);            if ((a_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) &&            (a_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 (ffs_dinode_copy(ffs, fs_file->meta)) {            tsk_fs_file_close(fs_file);            return 1;        }        retval = action(fs_file, 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))        && (a_flags & TSK_FS_META_FLAG_ALLOC)        && (a_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 = action(fs_file, 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_ENUMffs_block_getflags(TSK_FS_INFO * a_fs, TSK_DADDR_T a_addr){    FFS_INFO *ffs = (FFS_INFO *) a_fs;    FFS_GRPNUM_T grp_num;    ffs_cgd *cg = 0;    TSK_DADDR_T frag_base = 0;    TSK_DADDR_T dblock_addr = 0;        /* first data block in group */    TSK_DADDR_T sblock_addr = 0;        /* super block in group */    unsigned char *freeblocks = NULL;    int flags;    grp_num = dtog_lcl(a_fs, ffs->fs.sb1, a_addr);    if (ffs_group_load(ffs, grp_num)) {        return 0;    }    cg = (ffs_cgd *) ffs->grp_buf;    freeblocks = (unsigned char *) cg_blksfree_lcl(a_fs, cg);    // get the base fragment for the group    frag_base = cgbase_lcl(a_fs, ffs->fs.sb1, grp_num);    // address of first data block in group    dblock_addr = cgdmin_lcl(a_fs, ffs->fs.sb1, grp_num);    // address of super block in group    sblock_addr = cgsblock_lcl(a_fs, ffs->fs.sb1, grp_num);    /* get the flags for this fragment     *     * Beware: FFS stores file data in the blocks between the start of a     * cylinder group and the start of its super block.     */    flags = (isset(freeblocks, a_addr - frag_base) ?        TSK_FS_BLOCK_FLAG_UNALLOC : TSK_FS_BLOCK_FLAG_ALLOC);    if (a_addr >= sblock_addr && a_addr < dblock_addr)        flags |= TSK_FS_BLOCK_FLAG_META;    else        flags |= TSK_FS_BLOCK_FLAG_CONT;    return flags;}/************************************************************************** * * BLOCK WALKING * **************************************************************************//* ffs_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_tffs_block_walk(TSK_FS_INFO * 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 action, void *ptr){    char *myname = "ffs_block_walk";    FFS_INFO *ffs = (FFS_INFO *) fs;    TSK_FS_BLOCK *fs_block;    TSK_DADDR_T addr;    char *cache_blk_buf;        // buffer used for local read cache    TSK_DADDR_T cache_addr;     // base address in local cache    int cache_len_f;            // amount of data read into cache (in fragments)    // clean up any error messages that are lying around    tsk_error_reset();    /*     * Sanity checks on input bounds     */    if (a_start_blk < fs->first_block || a_start_blk > 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 < fs->first_block || a_end_blk > 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 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);    }    /* Other initialization */    if ((fs_block = tsk_fs_block_alloc(fs)) == NULL) {        return 1;    }    if ((cache_blk_buf = tsk_malloc(ffs->ffsbsize_b)) == NULL) {        return 1;    }    cache_len_f = 0;    cache_addr = 0;    /* Cycle through the fragment range requested */    for (addr = a_start_blk; addr <= a_end_blk; addr++) {        int retval;        int myflags = ffs_block_getflags(fs, addr);        if ((tsk_verbose) && (myflags & TSK_FS_BLOCK_FLAG_META)            && (myflags & TSK_FS_BLOCK_FLAG_UNALLOC))            tsk_fprintf(stderr,                "impossible: unallocated meta block %" PRIuDADDR, 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;        /* we read in block-sized chunks and cache the result for later         * calls.  See if this fragment is in our cache */        if ((cache_len_f == 0) || (addr >= cache_addr + cache_len_f)) {            ssize_t cnt;            int frags;            /* Ideally, we want to read in block sized chunks, verify we can do that */            frags = (a_end_blk > addr + ffs->ffsbsize_f - 1 ?                ffs->ffsbsize_f : (int) (a_end_blk + 1 - addr));            cnt =                tsk_fs_read_block(fs, addr, cache_blk_buf,                fs->block_size * frags);            if (cnt != fs->block_size * frags) {                if (cnt >= 0) {                    tsk_error_reset();                    tsk_errno = TSK_ERR_FS_READ;                }                snprintf(tsk_errstr2, TSK_ERRSTR_L,                    "ffs_block_walk: Block %" PRIuDADDR, addr);                tsk_fs_block_free(fs_block);                free(cache_blk_buf);                return 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -