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

📄 unix_misc.c

📁 linux下开发的针对所有磁盘的数据恢复的源码
💻 C
字号:
/* * The Sleuth Kit  * * Brian Carrier [carrier <at> sleuthkit [dot] org] * Copyright (c) 2008 Brian Carrier.  All Rights reserved * * This software is distributed under the Common Public License 1.0 *//** * \file unix_misc.c * Contains code that is common to both UFS1/2 and Ext2/3 file systems.  */#include "tsk_fs_i.h"#include "tsk_ffs.h"#include "tsk_ext2fs.h"/*********** MAKE DATA RUNS ***************//** \internal * Process an array of addresses and turn them into runs * * @param fs File system to analyze * @param fs_attr Data attribute to add runs to * @param addrs Buffer of addresses to process and turn into runs * @param addr_len Number of addresses in buffer * @param length Length of file remaining * * @returns the number of bytes processed and -1 if an error occurred */static TSK_OFF_Tunix_make_data_run_direct(TSK_FS_INFO * fs, TSK_FS_ATTR * fs_attr,    TSK_DADDR_T * addrs, size_t addr_len, TSK_OFF_T length){    TSK_DADDR_T run_start = 0;    TSK_DADDR_T run_len = 0;    TSK_DADDR_T blks_processed = 0;    size_t i;    size_t fs_blen;             // how big is each "block" (in fragments)    if (addr_len == 0) {        return 0;    }    // block_size is a fragment size in UFS, so we need to maintain length in fragments    if (TSK_FS_TYPE_ISFFS(fs->ftype)) {        FFS_INFO *ffs = (FFS_INFO *) fs;        fs_blen = ffs->ffsbsize_f;    }    else {        fs_blen = 1;    }    run_start = addrs[0];    run_len = fs_blen;    /* Note that we are lazy about length.  We stop only when a run is past length,     * we do not end exactly at length -- although that should happen anyway.       */    for (i = 0; i < addr_len; i++) {        /* Make a new run if:         * - This is the last addresss in the buffer         * - The next address is not part of the current run         * -- special case for sparse since they use 0 as an address         */        if ((i + 1 == addr_len) ||            ((run_start + run_len != addrs[i + 1]) && (run_start != 0)) ||            ((run_start == 0) && (addrs[i + 1] != 0))) {            TSK_FS_ATTR_RUN *data_run;            // make a non-resident run            data_run = tsk_fs_attr_run_alloc();            if (data_run == NULL)                return -1;            data_run->addr = run_start;            data_run->len = run_len;            if (run_start == 0)                data_run->flags = TSK_FS_ATTR_RUN_FLAG_SPARSE;            // save the run            tsk_fs_attr_append_run(fs, fs_attr, data_run);            // get ready for the next run            if (i + 1 != addr_len)                run_start = addrs[i + 1];            run_len = 0;            // stop if we are past the length requested            if (blks_processed * fs->block_size > (TSK_DADDR_T) length)                break;        }        run_len += fs_blen;        blks_processed += fs_blen;    }    return blks_processed * fs->block_size;}/** \internal * Read an indirect block and process the contents to make a runlist from the pointers.  * * @param fs File system to analyze * @param fs_attr Structure to save run data into * @param buf Buffers to read block data into (0 is block sized, 1+ are DADDR_T arrays based on FS type) * @param level Indirection level that this will process at (1+) * @param addr Address of block to read * @param length Length of file remaining * * @returns the number of bytes processed during call and -1 if an error occurred */static TSK_OFF_Tunix_make_data_run_indirect(TSK_FS_INFO * fs, TSK_FS_ATTR * fs_attr,    char *buf[], int level, TSK_DADDR_T addr, TSK_OFF_T length){    char *myname = "unix_make_data_run_indirect";    size_t addr_cnt = 0;    TSK_DADDR_T *myaddrs = (TSK_DADDR_T *) buf[level];    TSK_OFF_T length_remain = length;    TSK_OFF_T retval;    size_t fs_bufsize;    if (tsk_verbose)        tsk_fprintf(stderr, "%s: level %d block %" PRIuDADDR "\n", myname,            level, addr);    if (TSK_FS_TYPE_ISFFS(fs->ftype)) {        FFS_INFO *ffs = (FFS_INFO *) fs;        fs_bufsize = ffs->ffsbsize_b;    }    else {        fs_bufsize = fs->block_size;    }    if (addr > fs->last_block) {        tsk_error_reset();        tsk_errno = TSK_ERR_FS_INODE_COR;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "unix: Indirect block address too large: %" PRIuDADDR "",            addr);        return -1;    }    /*     * Read a block of disk addresses.     */    // sparse    if (addr == 0) {        memset(buf[0], 0, fs_bufsize);    }    else {        ssize_t cnt;        // read the data into the scratch buffer        cnt = tsk_fs_read_block(fs, addr, buf[0], fs_bufsize);        if (cnt != fs_bufsize) {            if (cnt >= 0) {                tsk_error_reset();                tsk_errno = TSK_ERR_FS_READ;            }            snprintf(tsk_errstr2, TSK_ERRSTR_L,                "unix_make_data_run_indir: Block %" PRIuDADDR, addr);            return -1;        }        // @@@ what do we do about META....    }    // convert the raw addresses to the correct endian ordering    if ((fs->ftype == TSK_FS_TYPE_FFS1)        || (fs->ftype == TSK_FS_TYPE_FFS1B)        || (TSK_FS_TYPE_ISEXT(fs->ftype))) {        size_t n;        uint32_t *iaddr = (uint32_t *) buf[0];        addr_cnt = fs_bufsize / sizeof(*iaddr);        for (n = 0; n < addr_cnt; n++) {            myaddrs[n] = tsk_getu32(fs->endian, (uint8_t *) & iaddr[n]);        }    }    else if (fs->ftype == TSK_FS_TYPE_FFS2) {        size_t n;        uint64_t *iaddr = (uint64_t *) buf[0];        addr_cnt = fs_bufsize / sizeof(*iaddr);        for (n = 0; n < addr_cnt; n++) {            myaddrs[n] = tsk_getu64(fs->endian, (uint8_t *) & iaddr[n]);        }    }    // pass the addresses to the next level    if (level == 1) {        retval =            unix_make_data_run_direct(fs, fs_attr, myaddrs, addr_cnt,            length_remain);        if (retval != -1) {            length_remain -= retval;        }    }    else {        size_t i;        retval = 0;        for (i = 0; i < addr_cnt && retval != -1; i++) {            retval =                unix_make_data_run_indirect(fs, fs_attr, buf, level - 1,                myaddrs[i], length_remain);            if (retval == -1) {                break;            }            else {                length_remain -= retval;            }        }    }    if (retval == -1)        return -1;    else        return length - length_remain;}/** \internal * * @returns 1 on error and 0 on success */uint8_ttsk_fs_unix_make_data_run(TSK_FS_FILE * fs_file){    TSK_OFF_T length = 0;    TSK_OFF_T read_b = 0;    TSK_FS_ATTR *fs_attr;    TSK_FS_META *fs_meta = fs_file->meta;    TSK_FS_INFO *fs = fs_file->fs_info;    // clean up any error messages that are lying around    tsk_error_reset();    if (tsk_verbose)        tsk_fprintf(stderr,            "unix_make_data_run: Processing file %" PRIuINUM "\n",            fs_meta->addr);    // see if we have already loaded the runs    if ((fs_meta->attr != NULL)        && (fs_meta->attr_state == TSK_FS_META_ATTR_STUDIED)) {        return 0;    }    else if (fs_meta->attr_state == TSK_FS_META_ATTR_ERROR) {        return 1;    }    // not sure why this would ever happen, but...    else if (fs_meta->attr != NULL) {        tsk_fs_attrlist_markunused(fs_meta->attr);    }    else if (fs_meta->attr == NULL) {        fs_meta->attr = tsk_fs_attrlist_alloc();    }    if ((TSK_FS_TYPE_ISFFS(fs->ftype) == 0)        && (TSK_FS_TYPE_ISEXT(fs->ftype) == 0)) {        tsk_errno = TSK_ERR_FS_INODE_COR;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "unix_make_run: Called with non-Unix file system: %x",            fs->ftype);        return 1;    }    length = roundup(fs_meta->size, fs->block_size);    if ((fs_attr =            tsk_fs_attrlist_getnew(fs_meta->attr,                TSK_FS_ATTR_NONRES)) == NULL) {        return 1;    }    // initialize the data run    if (tsk_fs_attr_set_run(fs_file, fs_attr, NULL, NULL,            TSK_FS_ATTR_TYPE_DEFAULT, TSK_FS_ATTR_ID_DEFAULT,            fs_meta->size, roundup(fs_meta->size, fs->block_size), 0, 0)) {        return 1;    }    read_b =        unix_make_data_run_direct(fs, fs_attr,        (TSK_DADDR_T *) fs_meta->content_ptr, 12, length);    if (read_b == -1) {        fs_meta->attr_state = TSK_FS_META_ATTR_ERROR;        if (fs_meta->flags & TSK_FS_META_FLAG_UNALLOC)            tsk_errno = TSK_ERR_FS_RECOVER;        return 1;    }    length -= read_b;    /* if there is still data left, read the indirect */    if (length > 0) {        int level;        char **buf;        size_t fs_bufsize0;        size_t fs_bufsize1;        /* With FFS/UFS a full block contains the addresses, but block_size is         * only a fragment.  Figure out the scratch buffer size and the buffers to          * store the cleaned addresses (endian converted) */        if (TSK_FS_TYPE_ISFFS(fs->ftype)) {            FFS_INFO *ffs = (FFS_INFO *) fs;            fs_bufsize0 = ffs->ffsbsize_b;            if ((fs->ftype == TSK_FS_TYPE_FFS1)                || (fs->ftype == TSK_FS_TYPE_FFS1B))                fs_bufsize1 = sizeof(TSK_DADDR_T) * ffs->ffsbsize_b / 4;            else                fs_bufsize1 = sizeof(TSK_DADDR_T) * ffs->ffsbsize_b / 8;        }        else {            fs_bufsize0 = fs->block_size;            fs_bufsize1 = sizeof(TSK_DADDR_T) * fs->block_size / 4;        }        /*         * Initialize a buffer for the 3 levels of indirection that are supported by         * this inode.  Each level of indirection will have a buffer to store         * addresses in.  buf[0] is a special scratch buffer that is used to store         * raw data from the image (before endian conversions are applied).  It is         * equal to one block size.  The others will store TSK_DADDR_T structures         * and will have a size depending on the FS type.          */        if ((buf = (char **) tsk_malloc(sizeof(char *) * 4)) == NULL)            return 1;        if ((buf[0] = (char *) tsk_malloc(fs_bufsize0)) == NULL) {            free(buf);            return 1;        }        for (level = 1; length > 0 && level < 4; level++) {            TSK_DADDR_T *addr_ptr = (TSK_DADDR_T *) fs_meta->content_ptr;            if ((buf[level] = (char *) tsk_malloc(fs_bufsize1)) == NULL) {                int f;                for (f = 0; f < level; f++)                    free(buf[f]);                free(buf);                return 1;            }            /* the indirect addresses are stored in addr_ptr after the 12             * direct addresses */            read_b =                unix_make_data_run_indirect(fs, fs_attr, buf, level,                addr_ptr[12 + level - 1], length);            if (read_b == -1)                break;            length -= read_b;        }        /*         * Cleanup.         */        for (level = 0; level < 4; level++) {            if (buf[level])                free(buf[level]);        }    }    if (read_b == -1) {        fs_meta->attr_state = TSK_FS_META_ATTR_ERROR;        if (fs_meta->flags & TSK_FS_META_FLAG_UNALLOC)            tsk_errno = TSK_ERR_FS_RECOVER;        return 1;    }    fs_meta->attr_state = TSK_FS_META_ATTR_STUDIED;    return 0;}TSK_FS_ATTR_TYPE_ENUMtsk_fs_unix_get_default_attr_type(const TSK_FS_FILE * a_file){    return TSK_FS_ATTR_TYPE_DEFAULT;}

⌨️ 快捷键说明

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