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

📄 hfs.c

📁 linux下开发的针对所有磁盘的数据恢复的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
                    if (out_ext != NULL)                        free(out_ext);                    return NULL;                }            }            /* iterate as long as this is associated with our file */            while (1) {                /* expand output extents record */                num_out_ext += 8;                if (out_ext) {  /* already allocated */                    out_ext = (hfs_ext_desc *)                        tsk_realloc((char *) out_ext,                        num_out_ext * sizeof(hfs_ext_desc));                }                else {          /* not already allocated */                    out_ext = (hfs_ext_desc *)                        tsk_malloc(num_out_ext * sizeof(hfs_ext_desc));                }                if (out_ext == NULL)                    return NULL;                /* if we've moved on to a different file (or fork), stop */                if ((tsk_getu32(fs->endian, key.file_id) != cnid) ||                    (key.fork_type[0] != 0)) {                    memset(((char *) out_ext) + (num_out_ext * 8 - 64), 0, 64);                    return out_ext;                }                /* read extents data */                if (hfs_checked_read_random(fs,                        ((char *) out_ext) + (num_out_ext * 8 - 64), 64,                        addr)) {                    snprintf(tsk_errstr2, TSK_ERRSTR_L,                        "hfs_ext_find_extent_record: reading extents data (record %"                        PRIu16 " node %" PRIu32 ")", rec, cur_node);                    free(out_ext);                    return NULL;                }                if (tsk_verbose) {                    for (i = num_out_ext - 8; i < num_out_ext; i++) {                        tsk_fprintf(stderr, "hfs_ext_find_extent_record: "                            "overflow extent start: %" PRIu32 ", length: %"                            PRIu32 "\n", tsk_getu32(fs->endian,                                out_ext[i].start_blk),                            tsk_getu32(fs->endian, out_ext[i].blk_cnt));                    }                }                /* according to Apple, if any start_blk and blk_cnt both == 0,                   we can stop, but we'll continue until we run out of                   extents for this file and fork regardless of their content */                /* go to the next record */                if ((hfs_ext_next_record(hfs, &rec, &num_rec, &node,                            &cur_node, &cur_off, &header)) == 0) {                    if (cur_node != 0) {                        snprintf(tsk_errstr2, TSK_ERRSTR_L,                            "hfs_ext_find_extent_record: advancing to next record (record %"                            PRIu16 " node %" PRIu32 ")", rec, cur_node);                        free(out_ext);                        return NULL;                    }                    /* ran out of records (file was at the end of the tree) */                    if (tsk_verbose)                        tsk_fprintf(stderr, "hfs_ext_find_extent_record: "                            "end of extents btree reached while finding extents\n");                    return out_ext;                }                /* load new key data */                addr = hfs_get_bt_rec_off(hfs, cur_off, leafsize, rec);                if (addr == 0) {                    snprintf(tsk_errstr2, TSK_ERRSTR_L,                        "hfs_ext_find_extent_record: finding record %"                        PRIu16 " in node %" PRIu32, rec, cur_node);                    free(out_ext);                    return NULL;                }                addr =                    hfs_read_key(hfs, &header, addr, (char *) &key,                    sizeof(hfs_ext_key), 1);                if (addr == 0) {                    snprintf(tsk_errstr2, TSK_ERRSTR_L,                        "hfs_ext_find_extent_record: reading key for record %"                        PRIu16 " in node %" PRIu32, rec, cur_node);                    free(out_ext);                    return NULL;                }            }        }        else {            tsk_errno = TSK_ERR_FS_GENFS;            snprintf(tsk_errstr, TSK_ERRSTR_L,                "hfs_ext_find_extent_record: btree node %" PRIu32                " (%" PRIu64 ") is neither index nor leaf (%" PRIu8 ")",                cur_node, cur_off, node.kind);            if (out_ext != NULL)                free(out_ext);            return NULL;        }    }}static TSK_FS_ATTR *hfs_forkdata_to_attr(TSK_FS_INFO * a_fs, const hfs_fork * a_fork){    TSK_FS_ATTR *attr;    int i;    if ((attr = tsk_fs_attr_alloc(TSK_FS_ATTR_NONRES)) == NULL)        return NULL;    for (i = 0; i < 8; i++) {        TSK_FS_ATTR_RUN *data_run;        uint32_t addr =            tsk_getu32(a_fs->endian, a_fork->extents[i].start_blk);        uint32_t len =            tsk_getu32(a_fs->endian, a_fork->extents[i].blk_cnt);        if ((addr == 0) && (len == 0))            break;        // make a non-resident run        data_run = tsk_fs_attr_run_alloc();        if (data_run == NULL)            return NULL;        data_run->addr = addr;        data_run->len = len;        tsk_fs_attr_append_run(a_fs, attr, data_run);    }    return attr;}// return 1 on errorstatic uint8_thfs_ext_find_extent_record_attr(HFS_INFO * hfs, uint32_t cnid,    TSK_FS_ATTR * a_head){    TSK_FS_INFO *fs = (TSK_FS_INFO *) & (hfs->fs_info);    uint16_t nodesize;          /* size of nodes (all, regardless of the name) */    uint32_t cur_node;          /* node id of the current node */    char *node = NULL;    tsk_error_reset();    if (hfs->extents_attr == NULL) {        ssize_t cnt;        hfs->catalog_attr = hfs_forkdata_to_attr(fs, &(hfs->fs->ext_file));        if (hfs->catalog_attr == NULL) {            // @@@ ERROR            return 1;        }        cnt = tsk_fs_attr_read(hfs->extents_attr, 14,            (char *) &(hfs->extents_header),            sizeof(hfs_btree_header_record), 0);        if (cnt != sizeof(hfs_btree_header_record)) {            // @@@            return 1;        }    }    nodesize = tsk_getu16(fs->endian, hfs->extents_header.nodesize);    if ((node = (char *) tsk_malloc(nodesize)) == NULL)        return 1;    // @@@ ADD FREE CODE    /* start at root node */    cur_node = tsk_getu32(fs->endian, hfs->extents_header.root);    /* if the root node is zero, then the extents btree is empty */    /* if no files have overflow extents, the Extents B-tree still       exists on disk, but is an empty B-tree containing only       the header node */    if (cur_node == 0) {        if (tsk_verbose)            tsk_fprintf(stderr, "hfs_ext_find_extent_record: "                "empty extents btree\n");        return 0;    }    if (tsk_verbose)        tsk_fprintf(stderr, "hfs_ext_find_extent_record: starting at "            "root node %" PRIu32 "; nodesize = %"            PRIu16 "\n", cur_node, nodesize);    while (1) {        TSK_OFF_T cur_off;      /* start address of cur_node */        uint16_t num_rec;       /* number of records in this node */        ssize_t cnt;        hfs_btree_node *node_desc;        cur_off = cur_node * nodesize;        cnt = tsk_fs_attr_read(hfs->extents_attr, cur_off,            node, nodesize, 0);        if (cnt != nodesize) {            // @@@            return 1;        }        node_desc = (hfs_btree_node *) node;        num_rec = tsk_getu16(fs->endian, node_desc->num_rec);        if (tsk_verbose)            tsk_fprintf(stderr, "hfs_ext_find_extent_record: node %" PRIu32                " @ %" PRIu64 " has %" PRIu16 " records\n",                cur_node, cur_off, num_rec);        if (num_rec == 0) {            tsk_errno = TSK_ERR_FS_GENFS;            snprintf(tsk_errstr, TSK_ERRSTR_L,                "hfs_ext_find_extent_record: zero records in node %"                PRIu32, cur_node);            return 1;        }        if (node_desc->kind == HFS_BTREE_INDEX_NODE) {            uint32_t next_node = 0;            int rec;            /* find largest key smaller than or equal to cnid */            for (rec = 0; rec < num_rec; rec++) {                int cmp;                size_t rec_off;                hfs_ext_key *key;                // get the record offset in the node                rec_off =                    tsk_getu32(fs->endian,                    &node[nodesize - (rec + 1) * 4]);                if (rec_off > nodesize) {                    // @@@ ERROR                }                key = (hfs_ext_key *) & node[rec_off];                cmp = hfs_compare_extent_keys(hfs, cnid, key);                if (tsk_verbose)                    tsk_fprintf(stderr,                        "hfs_ext_find_extent_record: record %" PRIu16                        " ; keylen %" PRIu16 " (%" PRIu32                        ", %" PRIu8 ", %" PRIu32 "); compare: %d\n", rec,                         tsk_getu16(fs->endian, key->key_len),                        tsk_getu32(fs->endian, key->file_id),                        key->fork_type[0], tsk_getu32(fs->endian,                            key->start_block), cmp);                /* find the largest key less than or equal to our key */                /* if all keys are larger than our key, select the leftmost key */                if ((cmp <= 0) || (next_node == 0)) {                    int keylen = tsk_getu16(fs->endian, key->key_len);                    // @@@ SANITY CHECK ON NODELEN AND rec_addr+keylen                    next_node =                        tsk_getu32(fs->endian, &node[rec_off + keylen]);                }                else {                    break;                }            }            if (next_node == 0) {                // @@@@            }            cur_node = next_node;        }        else if (node_desc->kind == HFS_BTREE_LEAF_NODE) {            int rec;            for (rec = 0; rec < num_rec; rec++) {                int i;                size_t rec_off;                hfs_ext_key *key;                uint32_t rec_cnid;                hfs_extents *extents;                TSK_OFF_T ext_off = 0;				int keylen;                // get the record offset in the node                rec_off =                    tsk_getu32(fs->endian,                    &node[nodesize - (rec + 1) * 4]);                if (rec_off > nodesize) {                    // @@@ ERROR                }                key = (hfs_ext_key *) & node[rec_off];                if (tsk_verbose)                    tsk_fprintf(stderr,                        "hfs_ext_find_extent_record: record %" PRIu16                        "; keylen %" PRIu16 " (%" PRIu32                        ", %" PRIu8 ", %" PRIu32 ")\n", rec,                         tsk_getu16(fs->endian, key->key_len),                        tsk_getu32(fs->endian, key->file_id),                        key->fork_type[0], tsk_getu32(fs->endian,                            key->start_block));                rec_cnid = tsk_getu32(fs->endian, key->file_id);                // see if this record is for our file                if (rec_cnid < cnid)                    continue;                else if ((rec_cnid > cnid) || (key->fork_type[0] != 0))                    break;                // get the starting offset of this extent                ext_off = tsk_getu32(fs->endian, key->start_block);                keylen = tsk_getu16(fs->endian, key->key_len);                // @@@ SANITY CHECK ON NODELEN AND rec_addr+2+keylen                extents = (hfs_extents *) & node[rec_off + keylen];                for (i = 0; i < 8; i++) {                    TSK_FS_ATTR_RUN *run;                    if ((tsk_getu32(fs->endian,                                extents->ext[i].start_blk) == 0)                        || (tsk_getu32(fs->endian,                                extents->ext[i].blk_cnt) == 0)) {                        break;                    }                    if ((run = tsk_fs_attr_run_alloc()) == NULL) {                        // @@@                        return 1;                    }                    run->offset = ext_off;                    run->addr =                        tsk_getu32(fs->endian, extents->ext[i].start_blk);                    run->len =                        tsk_getu32(fs->endian, extents->ext[i].blk_cnt);                    if (tsk_fs_attr_add_run(fs, a_head, run)) {                        // @@@                        return 1;                    }                    ext_off += run->len;                }            }        }        else {            tsk_errno = TSK_ERR_FS_GENFS;            snprintf(tsk_errstr, TSK_ERRSTR_L,                "hfs_ext_find_extent_record: btree node %" PRIu32                " (%" PRIu64 ") is neither index nor leaf (%" PRIu8 ")",                cur_node, cur_off, node_desc->kind);            return 1;        }    }}/* return the offset into the image that catalog btree node 'node' is at *//* returns 0 on failure; may set up to error string 1 */TSK_OFF_Thfs_cat_find_node_offset(HFS_INFO * hfs, uint32_t nodenum){    TSK_FS_INFO *fs = (TSK_FS_INFO *) & (hfs->fs_info);    uint16_t nodesize;          /* size of each node */    int i;    uint64_t bytes;             /* bytes left this extent */    TSK_OFF_T r_offs;           /* offset we are reading from */    TSK_OFF_T f_offs;           /* offset into the catalog file */    TSK_OFF_T n_offs;           /* offset of the node we are looking for */

⌨️ 快捷键说明

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