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

📄 hfs.c

📁 linux下开发的针对所有磁盘的数据恢复的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    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 + -