📄 hfs.c
字号:
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 + -