Example #1
0
static uint8_t
hfs_dir_open_meta_cb(HFS_INFO * hfs, int8_t level_type,
                     const void *targ_data, const hfs_btree_key_cat * cur_key,
                     TSK_OFF_T key_off, void *ptr)
{
    uint32_t *cnid_p = (uint32_t *) targ_data;
    HFS_DIR_OPEN_META_INFO *info = (HFS_DIR_OPEN_META_INFO *) ptr;
    TSK_FS_INFO *fs = &hfs->fs_info;

    if (tsk_verbose)
        fprintf(stderr,
                "hfs_dir_open_meta_cb: want %" PRIu32 " vs got %" PRIu32
                " (%s node)\n", *cnid_p, tsk_getu32(hfs->fs_info.endian,
                        cur_key->parent_cnid),
                (level_type == HFS_BT_NODE_TYPE_IDX) ? "Index" : "Leaf");

    if (level_type == HFS_BT_NODE_TYPE_IDX) {
        if (tsk_getu32(hfs->fs_info.endian,
                       cur_key->parent_cnid) < *cnid_p) {
            return HFS_BTREE_CB_IDX_LT;
        }
        else {
            return HFS_BTREE_CB_IDX_EQGT;
        }
    }
    else {
        uint8_t *rec_buf = (uint8_t *) cur_key;
        uint16_t rec_type;
        size_t rec_off2;

        if (tsk_getu32(hfs->fs_info.endian,
                       cur_key->parent_cnid) < *cnid_p) {
            return HFS_BTREE_CB_LEAF_GO;
        }
        else if (tsk_getu32(hfs->fs_info.endian,
                            cur_key->parent_cnid) > *cnid_p) {
            return HFS_BTREE_CB_LEAF_STOP;
        }
        rec_off2 = 2 + tsk_getu16(hfs->fs_info.endian, cur_key->key_len);
        // @@@ NEED TO REPLACE THIS SOMEHOW, but need to figure out the max length
        /*
           if (rec_off2 > nodesize) {
           tsk_error_set_errno(TSK_ERR_FS_GENFS);
           tsk_error_set_errstr(
           "hfs_dir_open_meta: offset of record+keylen %d in leaf node %d too large (%zu vs %"
           PRIu16 ")", rec, cur_node, rec_off2, nodesize);
           tsk_fs_name_free(fs_name);
           free(node);
           return TSK_COR;
           }
         */
        rec_type = tsk_getu16(hfs->fs_info.endian, &rec_buf[rec_off2]);

        // Catalog entry is for a file
        if (rec_type == HFS_FILE_THREAD) {
            tsk_error_set_errno(TSK_ERR_FS_GENFS);
            tsk_error_set_errstr("hfs_dir_open_meta: Entry"
                                 " is a file, not a folder");
            return HFS_BTREE_CB_ERR;
        }

        /* This will link the folder to its parent, which is the ".." entry */
        else if (rec_type == HFS_FOLDER_THREAD) {
            hfs_thread *thread = (hfs_thread *) & rec_buf[rec_off2];
            strcpy(info->fs_name->name, "..");
            info->fs_name->meta_addr =
                tsk_getu32(hfs->fs_info.endian, thread->parent_cnid);
            info->fs_name->type = TSK_FS_NAME_TYPE_DIR;
            info->fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;
        }

        /* This is a folder in the folder */
        else if (rec_type == HFS_FOLDER_RECORD) {
            hfs_folder *folder = (hfs_folder *) & rec_buf[rec_off2];

            info->fs_name->meta_addr =
                tsk_getu32(hfs->fs_info.endian, folder->std.cnid);
            info->fs_name->type = TSK_FS_NAME_TYPE_DIR;
            info->fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;


            if (hfs_UTF16toUTF8(fs, (uint8_t *) cur_key->name.unicode,
                                tsk_getu16(hfs->fs_info.endian, cur_key->name.length),
                                info->fs_name->name, HFS_MAXNAMLEN + 1,
                                HFS_U16U8_FLAG_REPLACE_SLASH)) {
                return HFS_BTREE_CB_ERR;
            }
        }

        /* This is a normal file in the folder */
        else if (rec_type == HFS_FILE_RECORD) {
            hfs_file *file = (hfs_file *) & rec_buf[rec_off2];
            // This could be a hard link.  We need to test this CNID, and follow it if necessary.
            unsigned char is_err;
            TSK_INUM_T file_cnid =
                tsk_getu32(hfs->fs_info.endian, file->std.cnid);
            TSK_INUM_T target_cnid =
                hfs_follow_hard_link(hfs, file, &is_err);
            if (is_err > 1) {
                error_returned
                ("hfs_dir_open_meta_cb: trying to follow a possible hard link in the directory");
                return HFS_BTREE_CB_ERR;
            }
            if (target_cnid != file_cnid) {
                HFS_ENTRY entry;
                uint8_t lkup;   // lookup result

                // This is a hard link.  We need to fill in the name->type and name->meta_addr from the target
                info->fs_name->meta_addr = target_cnid;
                // get the Catalog entry for the target CNID

                lkup = hfs_cat_file_lookup(hfs, target_cnid, &entry,
                                           FALSE);
                if (lkup != 0) {
                    error_returned
                    ("hfs_dir_open_meta_cb: retrieving the catalog entry for the target of a hard link");
                    return HFS_BTREE_CB_ERR;
                }
                info->fs_name->type =
                    hfsmode2tsknametype(tsk_getu16(hfs->fs_info.endian,
                                                   entry.cat.std.perm.mode));
            }
            else {
                // This is NOT a hard link.
                info->fs_name->meta_addr =
                    tsk_getu32(hfs->fs_info.endian, file->std.cnid);
                info->fs_name->type =
                    hfsmode2tsknametype(tsk_getu16(hfs->fs_info.endian,
                                                   file->std.perm.mode));
            }
            info->fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;
            if (hfs_UTF16toUTF8(fs, (uint8_t *) cur_key->name.unicode,
                                tsk_getu16(hfs->fs_info.endian, cur_key->name.length),
                                info->fs_name->name, HFS_MAXNAMLEN + 1,
                                HFS_U16U8_FLAG_REPLACE_SLASH)) {
                return HFS_BTREE_CB_ERR;
            }
        }
        else {
            tsk_error_set_errno(TSK_ERR_FS_GENFS);
            // @@@ MAY NEED TO IMPROVE BELOW MESSAGE
            tsk_error_set_errstr
            ("hfs_dir_open_meta: Unknown record type %d in leaf node",
             rec_type);
            return HFS_BTREE_CB_ERR;
        }

        if (tsk_fs_dir_add(info->fs_dir, info->fs_name)) {
            return HFS_BTREE_CB_ERR;
        }
        return HFS_BTREE_CB_LEAF_GO;
    }
}
Example #2
0
static uint8_t
hfs_dir_open_meta_cb(HFS_INFO * hfs, int8_t level_type,
    const void *targ_data, const hfs_btree_key_cat * cur_key,
    TSK_OFF_T key_off, void *ptr)
{
    uint32_t *cnid_p = (uint32_t *) targ_data;
    HFS_DIR_OPEN_META_INFO *info = (HFS_DIR_OPEN_META_INFO *) ptr;
    TSK_FS_INFO *fs = &hfs->fs_info;

    if (tsk_verbose)
        fprintf(stderr,
            "hfs_dir_open_meta_cb: want %" PRIu32 " vs got %" PRIu32
            " (%s node)\n", *cnid_p, tsk_getu32(hfs->fs_info.endian,
                cur_key->parent_cnid),
            (level_type == HFS_BT_NODE_TYPE_IDX) ? "Index" : "Leaf");

    if (level_type == HFS_BT_NODE_TYPE_IDX) {
        if (tsk_getu32(hfs->fs_info.endian,
                cur_key->parent_cnid) < *cnid_p)
            return HFS_BTREE_CB_IDX_LT;
        else
            return HFS_BTREE_CB_IDX_EQGT;
    }
    else {
        uint8_t *rec_buf = (uint8_t *) cur_key;
        uint16_t rec_type;
        size_t rec_off2;

        if (tsk_getu32(hfs->fs_info.endian,
                cur_key->parent_cnid) < *cnid_p)
            return HFS_BTREE_CB_LEAF_GO;
        else if (tsk_getu32(hfs->fs_info.endian,
                cur_key->parent_cnid) > *cnid_p)
            return HFS_BTREE_CB_LEAF_STOP;

        rec_off2 = 2 + tsk_getu16(hfs->fs_info.endian, cur_key->key_len);
        // @@@ NEED TO REPLACE THIS SOMEHOW, but need to figure out the max length
        /*
           if (rec_off2 > nodesize) {
           tsk_errno = TSK_ERR_FS_GENFS;
           snprintf(tsk_errstr, TSK_ERRSTR_L,
           "hfs_dir_open_meta: offset of record+keylen %d in leaf node %d too large (%zu vs %"
           PRIu16 ")", rec, cur_node, rec_off2, nodesize);
           tsk_fs_name_free(fs_name);
           free(node);
           return TSK_COR;
           }
         */
        rec_type = tsk_getu16(hfs->fs_info.endian, &rec_buf[rec_off2]);

        // Catalog entry is for a file
        if (rec_type == HFS_FILE_THREAD) {
            tsk_errno = TSK_ERR_FS_GENFS;
            snprintf(tsk_errstr, TSK_ERRSTR_L,
                "hfs_dir_open_meta: Entry" " is a file, not a folder");
            return HFS_BTREE_CB_ERR;
        }

        /* This will link the folder to its parent, which is the ".." entry */
        else if (rec_type == HFS_FOLDER_THREAD) {
            hfs_thread *thread = (hfs_thread *) & rec_buf[rec_off2];
            strcpy(info->fs_name->name, "..");
            info->fs_name->meta_addr =
                tsk_getu32(hfs->fs_info.endian, thread->parent_cnid);
            info->fs_name->type = TSK_FS_NAME_TYPE_DIR;
            info->fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;
        }

        /* This is a folder in the folder */
        else if (rec_type == HFS_FOLDER_RECORD) {
            hfs_folder *folder = (hfs_folder *) & rec_buf[rec_off2];

            info->fs_name->meta_addr =
                tsk_getu32(hfs->fs_info.endian, folder->std.cnid);
            info->fs_name->type = TSK_FS_NAME_TYPE_DIR;
            info->fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;


            if (hfs_uni2ascii(fs, (uint8_t *) cur_key->name.unicode,
                    tsk_getu16(hfs->fs_info.endian, cur_key->name.length),
                    info->fs_name->name, HFS_MAXNAMLEN + 1)) {
                return HFS_BTREE_CB_ERR;
            }
        }

        /* This is a normal file in the folder */
        else if (rec_type == HFS_FILE_RECORD) {
            hfs_file *file = (hfs_file *) & rec_buf[rec_off2];
            info->fs_name->meta_addr =
                tsk_getu32(hfs->fs_info.endian, file->std.cnid);
            info->fs_name->type =
                hfsmode2tsknametype(tsk_getu16(hfs->fs_info.endian,
                    file->std.perm.mode));
            info->fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;
            if (hfs_uni2ascii(fs, (uint8_t *) cur_key->name.unicode,
                    tsk_getu16(hfs->fs_info.endian, cur_key->name.length),
                    info->fs_name->name, HFS_MAXNAMLEN + 1)) {
                return HFS_BTREE_CB_ERR;
            }
        }
        else {
            tsk_errno = TSK_ERR_FS_GENFS;
            // @@@ MAY NEED TO IMPROVE BELOW MESSAGE
            snprintf(tsk_errstr, TSK_ERRSTR_L,
                "hfs_dir_open_meta: Unknown record type %d in leaf node",
                rec_type);
            return HFS_BTREE_CB_ERR;
        }

        if (tsk_fs_dir_add(info->fs_dir, info->fs_name)) {
            return HFS_BTREE_CB_ERR;
        }
        return HFS_BTREE_CB_LEAF_GO;
    }
}