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

📄 ffs.c

📁 linux下开发的针对所有磁盘的数据恢复的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*** The Sleuth Kit **** Brian Carrier [carrier <at> sleuthkit [dot] org]** Copyright (c) 2006-2008 Brian Carrier, Basis Technology.  All Rights reserved** Copyright (c) 2003-2005 Brian Carrier.  All rights reserved **** TASK** Copyright (c) 2002-2003 Brian Carrier, @stake Inc.  All rights reserved** ** Copyright (c) 1997,1998,1999, International Business Machines          ** Corporation and others. All Rights Reserved.*//* TCT  * LICENSE *	This software is distributed under the IBM Public License. * AUTHOR(S) *	Wietse Venema *	IBM T.J. Watson Research *	P.O. Box 704 *	Yorktown Heights, NY 10598, USA --*//** * \file ffs.c * Contains the internal TSK UFS / FFS file system functions */#include "tsk_fs_i.h"#include "tsk_ffs.h"/* ffs_group_load - load cylinder group descriptor info into cache  * * return 1 on error and 0 on success * */static uint8_tffs_group_load(FFS_INFO * ffs, FFS_GRPNUM_T grp_num){    TSK_DADDR_T addr;    TSK_FS_INFO *fs = (TSK_FS_INFO *) & ffs->fs_info;    /*     * Sanity check     */    if (grp_num < 0 || grp_num >= ffs->groups_count) {        tsk_error_reset();        tsk_errno = TSK_ERR_FS_ARG;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "ffs_group_load: invalid cylinder group number: %"            PRI_FFSGRP "", grp_num);        return 1;    }    /*     * Allocate/read cylinder group info on the fly. Trust that a cylinder     * group always fits within a logical disk block (as promised in the     * 4.4BSD <ufs/ffs/fs.h> include file).     */    if (ffs->grp_buf == NULL) {        if ((ffs->grp_buf = tsk_malloc(ffs->ffsbsize_b)) == NULL)            return 1;    }    addr = cgtod_lcl(fs, ffs->fs.sb1, grp_num);    if (ffs->grp_addr != addr) {        ffs_cgd *cg;        ssize_t cnt;        cnt = tsk_fs_read_block(fs, addr, ffs->grp_buf, ffs->ffsbsize_b);        if (cnt != ffs->ffsbsize_b) {            if (cnt >= 0) {                tsk_error_reset();                tsk_errno = TSK_ERR_FS_READ;            }            snprintf(tsk_errstr2, TSK_ERRSTR_L,                "ffs_group_load: Group %" PRI_FFSGRP " at %" PRIuDADDR,                grp_num, addr);            return 1;        }        ffs->grp_addr = addr;        /* Perform a sanity check on the data to make sure offsets are in range */        cg = (ffs_cgd *) ffs->grp_buf;        if ((tsk_gets32(fs->endian, cg->cg_iusedoff) > ffs->ffsbsize_b)            || (tsk_gets32(fs->endian, cg->cg_freeoff) > ffs->ffsbsize_b)) {            tsk_error_reset();            tsk_errno = TSK_ERR_FS_CORRUPT;            snprintf(tsk_errstr2, TSK_ERRSTR_L,                "ffs_group_load: Group %" PRI_FFSGRP                " descriptor offsets too large at %" PRIuDADDR, grp_num,                addr);            return 1;        }    }    ffs->grp_num = grp_num;    return 0;}/*  * ffs_dinode_load - read disk inode and load into local cache (ffs->dino_buf) * * Return 0 on success and 1 on error */static uint8_tffs_dinode_load(FFS_INFO * ffs, TSK_INUM_T inum){    TSK_DADDR_T addr;    TSK_OFF_T offs;    TSK_FS_INFO *fs = (TSK_FS_INFO *) & ffs->fs_info;    /*     * Sanity check.     * Use last_num-1 to account for virtual Orphan directory in last_inum.     */    if (inum < fs->first_inum || inum > fs->last_inum - 1) {        tsk_error_reset();        tsk_errno = TSK_ERR_FS_INODE_NUM;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "ffs_dinode_load: address: %" PRIuINUM, inum);        return 1;    }    /*     * Allocate/read the inode table buffer on the fly.     */    if (ffs->itbl_buf == NULL) {        if ((ffs->itbl_buf = tsk_malloc(ffs->ffsbsize_b)) == NULL)            return 1;    }    /* UFS2 is different because it does not initialize all inodes     * when the file system is created.  Therefore we need to check     * the group descriptor to find out if this is in the valid     * range     */    if (fs->ftype == TSK_FS_TYPE_FFS2) {        ffs_cgd2 *cg2;        FFS_GRPNUM_T grp_num;        if (ffs->dino_buf == NULL) {            ffs->dino_buf = (char *) tsk_malloc(sizeof(ffs_inode2));            if (ffs->dino_buf == NULL)                return 1;        }        else if (ffs->dino_inum == inum) {            return 0;        }        /* Lookup the cylinder group descriptor if it isn't         * cached         */        grp_num = (FFS_GRPNUM_T) 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;            }        }        cg2 = (ffs_cgd2 *) ffs->grp_buf;        /* If the inode is not init, then do not worry about it */        if ((inum - grp_num * tsk_getu32(fs->endian,                    ffs->fs.sb2->cg_inode_num)) >= tsk_getu32(fs->endian,                cg2->cg_initediblk)) {            memset((char *) ffs->dino_buf, 0, sizeof(ffs_inode2));        }        else {            ssize_t cnt;            /* Get the base and offset addr for the inode in the tbl */            addr = itod_lcl(fs, ffs->fs.sb1, inum);            if (ffs->itbl_addr != addr) {                cnt = tsk_fs_read_block                    (fs, addr, ffs->itbl_buf, ffs->ffsbsize_b);                if (cnt != ffs->ffsbsize_b) {                    if (cnt >= 0) {                        tsk_error_reset();                        tsk_errno = TSK_ERR_FS_READ;                    }                    snprintf(tsk_errstr2, TSK_ERRSTR_L,                        "ffs_dinode_load: FFS2 inode table at %"                        PRIuDADDR, addr);                    return 1;                }                ffs->itbl_addr = addr;            }            offs = itoo_lcl(fs, ffs->fs.sb2, inum) * sizeof(ffs_inode2);            memcpy((char *) ffs->dino_buf, ffs->itbl_buf + offs,                sizeof(ffs_inode2));        }    }    else {        if (ffs->dino_buf == NULL) {            ffs->dino_buf = (char *) tsk_malloc(sizeof(ffs_inode1));            if (ffs->dino_buf == NULL)                return 1;        }        else if (ffs->dino_inum == inum) {            return 0;        }        addr = itod_lcl(fs, ffs->fs.sb1, inum);        if (ffs->itbl_addr != addr) {            ssize_t cnt;            cnt =                tsk_fs_read_block(fs, addr, ffs->itbl_buf,                ffs->ffsbsize_b);            if (cnt != ffs->ffsbsize_b) {                if (cnt >= 0) {                    tsk_error_reset();                    tsk_errno = TSK_ERR_FS_READ;                }                snprintf(tsk_errstr2, TSK_ERRSTR_L,                    "ffs_dinode_load: FFS1 inode table at %"                    PRIuDADDR, addr);                return 1;            }            ffs->itbl_addr = addr;        }        offs = itoo_lcl(fs, ffs->fs.sb1, inum) * sizeof(ffs_inode1);        memcpy((char *) ffs->dino_buf, ffs->itbl_buf + offs,            sizeof(ffs_inode1));    }    ffs->dino_inum = inum;    return 0;}static TSK_FS_META_TYPE_ENUMffsmode2tsktype(uint16_t a_mode){    switch (a_mode & FFS_IN_FMT) {    case FFS_IN_REG:        return TSK_FS_META_TYPE_REG;    case FFS_IN_DIR:        return TSK_FS_META_TYPE_DIR;    case FFS_IN_SOCK:        return TSK_FS_META_TYPE_SOCK;    case FFS_IN_LNK:        return TSK_FS_META_TYPE_LNK;    case FFS_IN_BLK:        return TSK_FS_META_TYPE_BLK;    case FFS_IN_CHR:        return TSK_FS_META_TYPE_CHR;    case FFS_IN_FIFO:        return TSK_FS_META_TYPE_FIFO;    case FFS_IN_SHAD:        return TSK_FS_META_TYPE_SHAD;    case FFS_IN_WHT:        return TSK_FS_META_TYPE_WHT;    default:        return TSK_FS_META_TYPE_UNDEF;    }}static uint16_tffsmode2tskmode(uint16_t a_mode){    uint16_t mode = 0;    if (a_mode & FFS_IN_ISUID)        mode |= TSK_FS_META_MODE_ISUID;    if (a_mode & FFS_IN_ISGID)        mode |= TSK_FS_META_MODE_ISGID;    if (a_mode & FFS_IN_ISVTX)        mode |= TSK_FS_META_MODE_ISVTX;    if (a_mode & FFS_IN_IRUSR)        mode |= TSK_FS_META_MODE_IRUSR;    if (a_mode & FFS_IN_IWUSR)        mode |= TSK_FS_META_MODE_IWUSR;    if (a_mode & FFS_IN_IXUSR)        mode |= TSK_FS_META_MODE_IXUSR;    if (a_mode & FFS_IN_IRGRP)        mode |= TSK_FS_META_MODE_IRGRP;    if (a_mode & FFS_IN_IWGRP)        mode |= TSK_FS_META_MODE_IWGRP;    if (a_mode & FFS_IN_IXGRP)        mode |= TSK_FS_META_MODE_IXGRP;    if (a_mode & FFS_IN_IROTH)        mode |= TSK_FS_META_MODE_IROTH;    if (a_mode & FFS_IN_IWOTH)        mode |= TSK_FS_META_MODE_IWOTH;    if (a_mode & FFS_IN_IXOTH)        mode |= TSK_FS_META_MODE_IXOTH;    return mode;}/* ffs_dinode_copy - copy cached disk inode to generic inode   * * Return 1 on error and 0 on success */static uint8_tffs_dinode_copy(FFS_INFO * ffs, TSK_FS_META * fs_meta){    int i, j;    unsigned int count;    TSK_FS_INFO *fs = &(ffs->fs_info);    FFS_GRPNUM_T grp_num;    ffs_cgd *cg;    unsigned char *inosused = NULL;    TSK_INUM_T ibase;    fs_meta->attr_state = TSK_FS_META_ATTR_EMPTY;    if (fs_meta->attr) {        tsk_fs_attrlist_markunused(fs_meta->attr);    }    fs_meta->flags = 0;    fs_meta->seq = 0;    /* If the symlink field is set from a previous run, then free it */    if (fs_meta->link) {        free(fs_meta->link);        fs_meta->link = NULL;    }    fs_meta->addr = ffs->dino_inum;    /* OpenBSD and FreeBSD style */    if (fs->ftype == TSK_FS_TYPE_FFS1) {        ffs_inode1 *in = (ffs_inode1 *) ffs->dino_buf;        TSK_DADDR_T *addr_ptr;        fs_meta->mode =            ffsmode2tskmode(tsk_getu16(fs->endian, in->di_mode));        fs_meta->type =            ffsmode2tsktype(tsk_getu16(fs->endian, in->di_mode));        fs_meta->nlink = tsk_gets16(fs->endian, in->di_nlink);        fs_meta->size = tsk_getu64(fs->endian, in->di_size);        fs_meta->uid = tsk_getu32(fs->endian, in->di_uid);        fs_meta->gid = tsk_getu32(fs->endian, in->di_gid);        fs_meta->mtime = tsk_gets32(fs->endian, in->di_mtime);        fs_meta->atime = tsk_gets32(fs->endian, in->di_atime);        fs_meta->ctime = tsk_gets32(fs->endian, in->di_ctime);        fs_meta->crtime = 0;        if (fs_meta->content_len < FFS_FILE_CONTENT_LEN) {            if ((fs_meta =                    tsk_fs_meta_realloc(fs_meta,                        FFS_FILE_CONTENT_LEN)) == NULL) {                return 1;            }        }        addr_ptr = (TSK_DADDR_T *) fs_meta->content_ptr;        for (i = 0; i < FFS_NDADDR; i++)            addr_ptr[i] = tsk_gets32(fs->endian, in->di_db[i]);        for (i = 0; i < FFS_NIADDR; i++)            addr_ptr[FFS_NDADDR + i] =                tsk_gets32(fs->endian, in->di_ib[i]);        /* set the link string (if the file is a link)          * The size check is a sanity check so that we don't try and allocate         * a huge amount of memory for a bad inode value         */        if ((fs_meta->type == TSK_FS_META_TYPE_LNK)            && (fs_meta->size < FFS_MAXPATHLEN)            && (fs_meta->size >= 0)) {            int i;            fs_meta->link = tsk_malloc((size_t) fs_meta->size + 1);            if (fs_meta->link == NULL) {                return 1;            }            count = 0;          /* index into the link array */            /* it is located directly in the pointers   */            if (fs_meta->size < 4 * (FFS_NDADDR + FFS_NIADDR)) {                char *ptr;                /* Direct block pointer locations */                for (i = 0; i < FFS_NDADDR && count < fs_meta->size; i++) {                    ptr = (char *) &in->di_db[i];                    for (j = 0; j < 4 && count < fs_meta->size; j++)                        fs_meta->link[count++] = ptr[j];                }                /* indirect block pointers */                for (i = 0; i < FFS_NIADDR && count < fs_meta->size; i++) {                    ptr = (char *) &in->di_ib[i];

⌨️ 快捷键说明

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