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

📄 ntfs.c

📁 linux下开发的针对所有磁盘的数据恢复的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
                        a_mft->upd_cnt) - 1) * a_ntfs->ssize_b) >            a_ntfs->mft_rsize_b)) {        tsk_error_reset();        tsk_errno = TSK_ERR_FS_INODE_COR;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "dinode_lookup: More Update Sequence Entries than MFT size");        return TSK_COR;    }    if (tsk_getu16(fs->endian, a_mft->upd_off) > a_ntfs->mft_rsize_b) {        tsk_error_reset();        tsk_errno = TSK_ERR_FS_INODE_COR;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "dinode_lookup: Update sequence offset larger than MFT size");        return TSK_COR;    }    /* Apply the update sequence structure template */    upd =        (ntfs_upd *) ((uintptr_t) a_mft + tsk_getu16(fs->endian,            a_mft->upd_off));    /* Get the sequence value that each 16-bit value should be */    sig_seq = tsk_getu16(fs->endian, upd->upd_val);    /* cycle through each sector */    for (i = 1; i < tsk_getu16(fs->endian, a_mft->upd_cnt); i++) {        uint8_t *new_val, *old_val;        /* The offset into the buffer of the value to analyze */        size_t offset = i * a_ntfs->ssize_b - 2;        /* get the current sequence value */        uint16_t cur_seq =            tsk_getu16(fs->endian, (uintptr_t) a_mft + offset);        if (cur_seq != sig_seq) {            /* get the replacement value */            uint16_t cur_repl =                tsk_getu16(fs->endian, &upd->upd_seq + (i - 1) * 2);            tsk_error_reset();            tsk_errno = TSK_ERR_FS_GENFS;            snprintf(tsk_errstr, TSK_ERRSTR_L,                "Incorrect update sequence value in MFT entry\nSignature Value: 0x%"                PRIx16 " Actual Value: 0x%" PRIx16                " Replacement Value: 0x%" PRIx16                "\nThis is typically because of a corrupted entry",                sig_seq, cur_seq, cur_repl);            return TSK_COR;        }        new_val = &upd->upd_seq + (i - 1) * 2;        old_val = (uint8_t *) ((uintptr_t) a_mft + offset);        if (tsk_verbose)            tsk_fprintf(stderr,                "ntfs_dinode_lookup: upd_seq %i   Replacing: %.4"                PRIx16 "   With: %.4" PRIx16 "\n", i,                tsk_getu16(fs->endian, old_val), tsk_getu16(fs->endian,                    new_val));        *old_val++ = *new_val++;        *old_val = *new_val;    }    return TSK_OK;}/* * given a cluster, return the allocation status or * -1 if an error occurs */static intis_clustalloc(NTFS_INFO * ntfs, TSK_DADDR_T addr){    int bits_p_clust, b;    TSK_DADDR_T base;    bits_p_clust = 8 * ntfs->fs_info.block_size;    /* While we are loading the MFT, assume that everything     * is allocated.  This should only be needed when we are     * dealing with an attribute list ...      */    if (ntfs->loading_the_MFT == 1) {        return 1;    }    else if (ntfs->bmap == NULL) {        tsk_error_reset();        tsk_errno = TSK_ERR_FS_ARG;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "is_clustalloc: Bitmap pointer is null: %" PRIuDADDR            "\n", addr);        return -1;    }    /* Is the cluster too big? */    if (addr > ntfs->fs_info.last_block) {        tsk_error_reset();        tsk_errno = TSK_ERR_FS_INODE_COR;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "is_clustalloc: cluster too large");        return -1;    }    /* identify the base cluster in the bitmap file */    base = addr / bits_p_clust;    b = (int) (addr % bits_p_clust);    /* is this the same as in the cached buffer? */    if (base != ntfs->bmap_buf_off) {        TSK_DADDR_T c = base;        TSK_FS_ATTR_RUN *run;        TSK_DADDR_T fsaddr = 0;        ssize_t cnt;        /* get the file system address of the bitmap cluster */        for (run = ntfs->bmap; run; run = run->next) {            if (run->len <= c) {                c -= run->len;            }            else {                fsaddr = run->addr + c;                break;            }        }        if (fsaddr == 0) {            tsk_error_reset();            tsk_errno = TSK_ERR_FS_BLK_NUM;            snprintf(tsk_errstr, TSK_ERRSTR_L,                "is_clustalloc: cluster not found in bitmap: %"                PRIuDADDR "", c);            return -1;        }        if (fsaddr > ntfs->fs_info.last_block) {            tsk_error_reset();            tsk_errno = TSK_ERR_FS_BLK_NUM;            snprintf(tsk_errstr, TSK_ERRSTR_L,                "is_clustalloc: Cluster in bitmap too large for image: %"                PRIuDADDR, fsaddr);            return -1;        }        ntfs->bmap_buf_off = base;        cnt = tsk_fs_read_block            (&ntfs->fs_info, fsaddr, ntfs->bmap_buf,            ntfs->fs_info.block_size);        if (cnt != ntfs->fs_info.block_size) {            if (cnt >= 0) {                tsk_error_reset();                tsk_errno = TSK_ERR_FS_READ;            }            snprintf(tsk_errstr2, TSK_ERRSTR_L,                "is_clustalloc: Error reading bitmap at %"                PRIuDADDR, fsaddr);            return -1;        }    }    /* identify if the cluster is allocated or not */    return (isset(ntfs->bmap_buf, b)) ? 1 : 0;}/********************************************************************** * *  TSK_FS_ATTR functions * **********************************************************************//** * Process a non-resident runlist and convert its contents into the generic fs_attr_run * structure.  * @param ntfs File system that attribute is located in. * @param start_vcn The starting VCN for this run.  * @param runlist The raw runlist data from the MFT entry. * @param a_data_run_head [out] Pointer to pointer of run that is created. (NULL on error and for $BadClust - special case because it is a sparse file for the entire FS). * @param totlen [out] Pointer to location where total length of run (in bytes) can be returned (or NULL) * * @returns Return status of error, corrupt, or OK (note a_data_run can be NULL even when OK is returned if $BadClust is encountered) */static TSK_RETVAL_ENUMntfs_make_data_run(NTFS_INFO * ntfs, TSK_OFF_T start_vcn,    ntfs_runlist * runlist_head, TSK_FS_ATTR_RUN ** a_data_run_head,    TSK_OFF_T * totlen){    TSK_FS_INFO *fs = (TSK_FS_INFO *) ntfs;    ntfs_runlist *run;    TSK_FS_ATTR_RUN *data_run, *data_run_prev = NULL;    unsigned int i, idx;    TSK_DADDR_T prev_addr = 0;    TSK_OFF_T file_offset = start_vcn;    run = runlist_head;    *a_data_run_head = NULL;    /* initialize if non-NULL */    if (totlen)        *totlen = 0;    /* Cycle through each run in the runlist      * We go until we find an entry with no length     * An entry with offset of 0 is for a sparse run     */    while (NTFS_RUNL_LENSZ(run) != 0) {        int64_t addr_offset = 0;        /* allocate a new tsk_fs_attr_run */        if ((data_run = tsk_fs_attr_run_alloc()) == NULL) {            tsk_fs_attr_run_free(*a_data_run_head);            *a_data_run_head = NULL;            return TSK_ERR;        }        /* make the list, unless its the first pass & then we set the head */        if (data_run_prev)            data_run_prev->next = data_run;        else            *a_data_run_head = data_run;        data_run_prev = data_run;        /* These fields are a variable number of bytes long         * these for loops are the equivalent of the getuX macros         */        idx = 0;        /* Get the length of this run */        for (i = 0, data_run->len = 0; i < NTFS_RUNL_LENSZ(run); i++) {            data_run->len |= (run->buf[idx++] << (i * 8));            if (tsk_verbose)                tsk_fprintf(stderr,                    "ntfs_make_data_run: Len idx: %i cur: %"                    PRIu8 " (%" PRIx8 ") tot: %" PRIuDADDR                    " (%" PRIxDADDR ")\n", i,                    run->buf[idx - 1], run->buf[idx - 1],                    data_run->len, data_run->len);        }        /* Sanity check on length */        if (data_run->len > fs->block_count) {            tsk_error_reset();            tsk_errno = TSK_ERR_FS_INODE_COR;            snprintf(tsk_errstr, TSK_ERRSTR_L,                "ntfs_make_run: Run length is larger than file system");            tsk_fs_attr_run_free(*a_data_run_head);            *a_data_run_head = NULL;            return TSK_COR;        }        data_run->offset = file_offset;        file_offset += data_run->len;        /* Update the length if we were passed a value */        if (totlen)            *totlen += (data_run->len * ntfs->csize_b);        /* Get the address of this run */        for (i = 0, data_run->addr = 0; i < NTFS_RUNL_OFFSZ(run); i++) {            //data_run->addr |= (run->buf[idx++] << (i * 8));            addr_offset |= (run->buf[idx++] << (i * 8));            if (tsk_verbose)                tsk_fprintf(stderr,                    "ntfs_make_data_run: Off idx: %i cur: %"                    PRIu8 " (%" PRIx8 ") tot: %" PRIuDADDR                    " (%" PRIxDADDR ")\n", i,                    run->buf[idx - 1], run->buf[idx - 1], addr_offset,                    addr_offset);        }        /* addr_offset value is signed so extend it to 64-bits */        if ((int8_t) run->buf[idx - 1] < 0) {            for (; i < sizeof(addr_offset); i++)                addr_offset |= (int64_t) ((int64_t) 0xff << (i * 8));        }        if (tsk_verbose)            tsk_fprintf(stderr,                "ntfs_make_data_run: Signed addr_offset: %"                PRIdDADDR " Previous address: %"                PRIdDADDR "\n", addr_offset, prev_addr);        /* The NT 4.0 version of NTFS uses an offset of -1 to represent         * a hole, so add the sparse flag and make it look like the 2K         * version with a offset of 0         *         * A user reported an issue where the $Bad file started with         * its offset as -1 and it was not NT (maybe a conversion)         * Change the check now to not limit to NT, but make sure         * that it is the first run         */        if (((addr_offset == -1) && (prev_addr == 0))            || ((addr_offset == -1)                && (ntfs->ver == NTFS_VINFO_NT))) {            data_run->flags |= TSK_FS_ATTR_RUN_FLAG_SPARSE;            data_run->addr = 0;            if (tsk_verbose)                tsk_fprintf(stderr, "ntfs_make_data_run: Sparse Run\n");        }        /* A Sparse file has a run with an offset of 0         * there is a special case though of the BOOT MFT entry which         * is the super block and has a legit offset of 0.         *         * The value given is a delta of the previous offset, so add          * them for non-sparse files         *         * For sparse files the next run will have its offset relative          * to the current "prev_addr" so skip that code         */        else if ((addr_offset) || (ntfs->mnum == NTFS_MFT_BOOT)) {            data_run->addr = prev_addr + addr_offset;            prev_addr = data_run->addr;            /* Sanity check on length and offset */            if (data_run->addr + data_run->len > fs->block_count) {                tsk_error_reset();                tsk_errno = TSK_ERR_FS_INODE_COR;                snprintf(tsk_errstr, TSK_ERRSTR_L,                    "ntfs_make_run: Run offset and length is larger than file system");                tsk_fs_attr_run_free(*a_data_run_head);                *a_data_run_head = NULL;                return TSK_COR;            }        }        else {            data_run->flags |= TSK_FS_ATTR_RUN_FLAG_SPARSE;            if (tsk_verbose)                tsk_fprintf(stderr, "ntfs_make_data_run: Sparse Run\n");        }        /* Advance run */        run = (ntfs_runlist *) ((uintptr_t) run + (1 + NTFS_RUNL_LENSZ(run)                + NTFS_RUNL_OFFSZ(run)));    }    /* special case for $BADCLUST, which is a sparse file whose size is     * the entire file system.     *     * If there is only one run entry and it is sparse, then there are no     * bad blocks, so get rid of it.     */    if ((*a_data_run_head != NULL)        && ((*a_data_run_head)->next == NULL)        && ((*a_data_run_head)->flags & TSK_FS_ATTR_RUN_FLAG_SPARSE)        && ((*a_data_run_head)->len == fs->last_block + 1)) {        tsk_fs_attr_run_free(*a_data_run_head);        *a_data_run_head = NULL;    }    return TSK_OK;}/*********** UNCOMPRESSION CODE *************//* * NTFS Breaks compressed data into compression units, which are * typically 16 clusters in size. If the data in the comp  unit * compresses to something smaller than 16 clusters then the * compresed data is stored and the rest of the compression unit

⌨️ 快捷键说明

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