📄 hfs.c
字号:
hfs_ext_desc *extents; if (tsk_verbose) tsk_fprintf(stderr, "hfs_cat_find_node_offset: finding offset of " "btree node: %" PRIu32 "\n", nodenum); extents = hfs->cat_extents; /* find first extent with data in it */ /* as above, holdover from previous code */ i = 0; while (!(tsk_getu32(fs->endian, extents[i].blk_cnt))) i++; if (i > 7) { tsk_errno = TSK_ERR_FS_GENFS; snprintf(tsk_errstr, TSK_ERRSTR_L, "hfs_cat_find_node_offset: no data found in catalog file extents"); return 0; } bytes = tsk_getu32(fs->endian, extents[i].blk_cnt) * (TSK_OFF_T) fs->block_size; r_offs = tsk_getu32(fs->endian, extents[i].start_blk) * (TSK_OFF_T) fs->block_size; f_offs = 0; nodesize = tsk_getu16(fs->endian, hfs->hdr->nodesize); /* calculate where we will find the 'nodenum' node */ n_offs = nodesize * nodenum; while (f_offs < n_offs) { if (n_offs <= (f_offs + (TSK_OFF_T)bytes)) { r_offs += n_offs - f_offs; f_offs = n_offs; } else { i++; if (i > 7) { tsk_errno = TSK_ERR_FS_GENFS; snprintf(tsk_errstr, TSK_ERRSTR_L, "hfs_cat_find_node_offset: file seek error while searching for node %" PRIu32 "\n", nodenum); return 0; } r_offs = tsk_getu32(fs->endian, extents[i].start_blk) * (TSK_OFF_T) fs->block_size; f_offs += bytes; bytes = tsk_getu32(fs->endian, extents[i].blk_cnt) * (TSK_OFF_T) fs->block_size; } } return r_offs;}/* Advances to the next record in the Catalog B-tree, given information about * where you currently are in the B-tree. * Assumes that you are actually keeping track of these many fields. They * must correctly contain the current values. If the current node is changed, * they will be changed to their new values. * Returns cur_node. If you have reached the end of the node chain (no more * records), cur_node will be set to zero and returned. * May set up to error string 2. Returns 0 on error. */uint32_thfs_cat_next_record(HFS_INFO * hfs, uint16_t * rec, uint16_t * num_rec, hfs_btree_node * node, uint32_t * cur_node, TSK_OFF_T * cur_off, hfs_btree_header_record * header){ TSK_FS_INFO *fs = (TSK_FS_INFO *) & (hfs->fs_info); tsk_error_reset(); (*rec)++; if (*rec >= *num_rec) { /* ran out of records in this node */ *cur_node = tsk_getu32(fs->endian, node->flink); if (*cur_node == 0) return *cur_node; *cur_off = hfs_cat_find_node_offset(hfs, *cur_node); if (*cur_off == 0) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "hfs_cat_next_record: find next node offset (%" PRIu32 ")", *cur_node); return 0; } if (hfs_checked_read_random(fs, (char *) node, sizeof(hfs_btree_node), *cur_off)) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "hfs_cat_next_record: read btree node %" PRIu32 " at %" PRIuDADDR, *cur_node, *cur_off); return 0; } *num_rec = tsk_getu16(fs->endian, node->num_rec); *rec = 0; if (tsk_verbose) tsk_fprintf(stderr, "hfs_cat_next_record: advanced to next node %" PRIu32 "(@ %" PRIu64 ", has %" PRIu16 "records \n", *cur_node, *cur_off, *num_rec); } else { if (tsk_verbose) tsk_fprintf(stderr, "hfs_cat_next_record: advanced to record %" PRIu16 "\n", *rec); } return *cur_node;}/** \internal * Returns the largest inode number in file system * @param hfs File system being analyzed * @returns largest metadata address */static TSK_INUM_Thfs_find_highest_inum(HFS_INFO * hfs){ // @@@ get actual number from Catalog file /* I haven't gotten looking at the end of the Catalog B-Tree to work properly. A fast method: if HFS_BIT_VOLUME_CNIDS_REUSED is set, then the maximum CNID is 2^32-1; if it's not set, then nextCatalogId is supposed to be larger than all CNIDs on disk. */ TSK_FS_INFO *fs = (TSK_FS_INFO *) & (hfs->fs_info); if (tsk_getu32(fs->endian, hfs->fs->attr) & HFS_BIT_VOLUME_CNIDS_REUSED) return (TSK_INUM_T) 0xffffffff; else return (TSK_INUM_T) tsk_getu32(fs->endian, hfs->fs->next_cat_id) - 1;}// @@@ We should have a version of this that allows one key to have cnid already in local order.../** \internal * Compares two Catalog B-tree keys. * @param hfs File System being analyzed * @param key1 Key 1 to compare * @param key2 Key 2 to compare * @returns -1 if key1 is smaller, 0 if equal, and 1 if key1 is larger */inthfs_compare_catalog_keys(HFS_INFO * hfs, hfs_cat_key * key1, hfs_cat_key * key2){ TSK_FS_INFO *fs = (TSK_FS_INFO *) & (hfs->fs_info); uint32_t cnid1, cnid2; cnid1 = tsk_getu32(fs->endian, key1->parent_cnid); cnid2 = tsk_getu32(fs->endian, key2->parent_cnid); if (cnid1 < cnid2) return -1; if (cnid1 > cnid2) return 1; return hfs_unicode_compare(hfs, &key1->name, &key2->name);}/** \internal * Find the byte offset (from the start of the disk) to a record * in the catalog file. * @param hfs File System being analyzed * @param needle Key to search for * @returns Byte offset or 0 on error. 0 is also returned if catalog * record was not found. Check tsk_errno to determine if error occured. */static TSK_OFF_Thfs_find_catalog_record(HFS_INFO * hfs, hfs_cat_key * needle){ TSK_FS_INFO *fs = (TSK_FS_INFO *) & (hfs->fs_info); hfs_btree_header_record header; /* header for the Catalog btree */ uint16_t leafsize; /* size of nodes (all, regardless of the name) */ uint32_t cur_node; /* node id of the current node */ TSK_OFF_T off; tsk_error_reset(); /* read catalog header record */ off = hfs_cat_find_node_offset(hfs, 0); if (off == 0) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "hfs_find_catalog_record: find catalog header node"); return 0; } off += 14; // sizeof header if (hfs_checked_read_random(fs, (char *) &header, sizeof(header), off)) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "hfs_find_catalog_record: read catalog header node"); return 0; } leafsize = tsk_getu16(fs->endian, header.nodesize); // @@@ This should be hard coded /* start at root node */ cur_node = tsk_getu32(fs->endian, header.root); if (tsk_verbose) tsk_fprintf(stderr, "hfs_find_catalog_record: starting at " "root node %" PRIu32 "; header @ %" PRIu64 "; leafsize = %" PRIu16 "\n", cur_node, off, leafsize); while (1) { TSK_OFF_T cur_off; /* start address of cur_node */ hfs_cat_key key; /* current key */ uint16_t num_rec; /* number of records in this node */ TSK_DADDR_T recaddr; uint16_t rec, recno; char buf[4]; int cmp; hfs_btree_node node; /* data of the current node */ /* load node header */ cur_off = hfs_cat_find_node_offset(hfs, cur_node); if (cur_off == 0) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "hfs_find_catalog_record: find catalog node %" PRIu32, cur_node); return 0; } if (hfs_checked_read_random(fs, (char *) &node, sizeof(node), cur_off)) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "hfs_find_catalog_record: read catalog node %" PRIu32 " at %" PRIuDADDR, cur_node, cur_off); return 0; } num_rec = tsk_getu16(fs->endian, node.num_rec); if (tsk_verbose) tsk_fprintf(stderr, "hfs_find_catalog_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_find_catalog_record: zero records in node %" PRIu32, cur_node); return 0; } /* find largest key smaller than or equal to our key */ recno = 0; recaddr = 0; for (rec = 0; rec < num_rec; rec++) { off = hfs_get_bt_rec_off(hfs, cur_off, leafsize, rec); if (off == 0) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "hfs_find_catalog_record: finding record %" PRIu16 " in node %" PRIu32, rec, cur_node); return 0; } off = hfs_read_key(hfs, &header, off, (char *) &key, sizeof(hfs_cat_key), 1); if (off == 0) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "hfs_find_catalog_record: reading record %" PRIu16 " in node %" PRIu32, rec, cur_node); return 0; } cmp = hfs_compare_catalog_keys(hfs, &key, needle); if (tsk_verbose) tsk_fprintf(stderr, "hfs_find_catalog_record: record %" PRIu16 " @ %" PRIu64 "; keylen %" PRIu16 " (%" PRIu32 ", %" PRIu16 "); compare: %d\n", rec, off, tsk_getu16(fs->endian, key.key_len), tsk_getu32(fs->endian, key.parent_cnid), tsk_getu16(fs->endian, key.name.length), 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) || (recaddr == 0)) { recaddr = off; recno = rec; } if (cmp >= 0) break; } if (node.kind == HFS_BTREE_INDEX_NODE) { /* replace cur node number with the node number referenced * by the found key, continue */ if (hfs_checked_read_random(fs, buf, 4, recaddr)) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "hfs_find_catalog_record: reading pointer in record %" PRIu16 " in node %" PRIu32, rec, cur_node); return 0; } cur_node = tsk_getu32(fs->endian, buf); } else if (node.kind == HFS_BTREE_LEAF_NODE) { rec = recno; /* reget key */ off = hfs_get_bt_rec_off(hfs, cur_off, leafsize, rec); if (off == 0) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "hfs_find_catalog_record: finding record %" PRIu16 " in node %" PRIu32, rec, cur_node); return 0; } off = hfs_read_key(hfs, &header, off, (char *) &key, sizeof(hfs_ext_key), 1); if (off == 0) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "hfs_find_catalog_record: reading record %" PRIu16 " in node %" PRIu32, rec, cur_node); return 0; } if (hfs_compare_catalog_keys(hfs, &key, needle) == 0) return off; return 0; /* this key not found */ } else { tsk_errno = TSK_ERR_FS_GENFS; snprintf(tsk_errstr, TSK_ERRSTR_L, "hfs_find_catalog_record: btree node %" PRIu32 " (%" PRIu64 ") is neither index nor leaf (%" PRIu8 ")", cur_node, cur_off, node.kind); return 0; } }}/* Thread records are variable-length. This function reads in from disk only that * data actually contained within the thread record into a fixed-size (maximum-size) * hfs_thread structure, zeroing the remainder of the structure * Returns 0 on success, 1 on failure; sets up to error string 1 */uint8_thfs_read_thread_record(HFS_INFO * hfs, TSK_DADDR_T addr, hfs_thread * thread){ TSK_FS_INFO *fs = (TSK_FS_INFO *) & (hfs->fs_info); uint16_t uni_len; memset(thread, 0, sizeof(hfs_thread)); if (hfs_checked_read_random(fs, (char *) thread, 10, addr)) return 1; if ((tsk_getu16(fs->endian, thread->record_type) != HFS_FOLDER_THREAD) && (tsk_getu16(fs->endian, thread->record_type) != HFS_FILE_THREAD)) { tsk_errno = TSK_ERR_FS_GENFS; snprintf(tsk_errstr, TSK_ERRSTR_L, "hfs_read_thread_record: unexpected record type %" PRIu16, tsk_getu16(fs->endian, thread->record_type)); return 1; } uni_len = tsk_getu16(fs->endian, thread->name.length);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -