Beispiel #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_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;
    }
}
Beispiel #2
0
uint8_t
hfs_dent_walk_lcl(TSK_FS_INFO * fs, HFS_DINFO * dinfo, INUM_T inum,
    TSK_FS_DENT_FLAG_ENUM flags, TSK_FS_DENT_TYPE_WALK_CB action,
    void *ptr)
{
    TSK_FS_DENT *fs_dent;
    HFS_INFO *hfs = (HFS_INFO *) fs;
    uint8_t ucs_fn[HFS_MAXNAMLEN * 2];
    uint16_t filetype;
    TSK_FS_INODE *fs_inode;
    DADDR_T offs;
    int keylen;
    uint8_t key_len[2];
    int j;
    INUM_T newinum;
    htsk_fs_inode_mode_struct *in;

    fs_dent = tsk_fs_dent_alloc(HFS_MAXNAMLEN, 0);

    if (tsk_verbose)
        fprintf(stderr, "hfs_dent_walk: Processing directory %lu\n",
            (ULONG) inum);

    if (inum < fs->first_inum || inum > fs->last_inum)
        tsk_fprintf(stderr, "invalid inode value: %i\n", inum);

    fs_inode = fs->inode_lookup(fs, inum);

    filetype = tsk_getu16(fs->endian, hfs->cat->rec_type);

    /*
     * "."
     */
    fs_dent->inode = inum;
    strcpy(fs_dent->name, ".");

    /* copy the path data */
    fs_dent->path = dinfo->dirs;
    fs_dent->pathdepth = dinfo->depth;
    fs_dent->fsi = fs->inode_lookup(fs, fs_dent->inode);

    fs_dent->ent_type = TSK_FS_DENT_TYPE_DIR;
    fs_dent->flags = TSK_FS_DENT_FLAG_ALLOC;

    if (TSK_WALK_STOP == action(fs, fs_dent, ptr)) {
        tsk_fs_dent_free(fs_dent);
        return 0;
    }

    /*
     * ".."
     */

    in = hfs->inodes + inum;

    /* the parent of root is 1, but there is no inode 1 */
    if (inum == HFS_ROOT_INUM)
        newinum = HFS_ROOT_INUM;
    else
        newinum = in->parent;

    fs_dent->inode = newinum;
    strcpy(fs_dent->name, "..");

    /* copy the path data */
    fs_dent->path = dinfo->dirs;
    fs_dent->pathdepth = dinfo->depth;
    fs_dent->fsi = fs->inode_lookup(fs, fs_dent->inode);

    fs_dent->ent_type = TSK_FS_DENT_TYPE_DIR;
    fs_dent->flags = TSK_FS_DENT_FLAG_ALLOC;

    if (TSK_WALK_STOP == action(fs, fs_dent, ptr)) {
        tsk_fs_dent_free(fs_dent);
        return 0;
    }

    /* because hfs->key (the filename offset) is reset with each lookup, this is necessary here... */
    fs_dent->inode = inum;
    fs_dent->path = dinfo->dirs;
    fs_dent->pathdepth = dinfo->depth;
    fs_dent->fsi = fs->inode_lookup(fs, fs_dent->inode);

    if (filetype == HFS_FOLDER_RECORD) {

        for (j = HFS_ROOT_INUM; j <= fs->last_inum; j++) {

            in = hfs->inodes + j;

            if (in->parent == inum) {

                newinum = j;

                fs_dent->inode = newinum;
                fs_dent->path = dinfo->dirs;
                fs_dent->pathdepth = dinfo->depth;
                fs_dent->fsi = fs->inode_lookup(fs, fs_dent->inode);

                offs = hfs->key;
                tsk_fs_read_random(fs, (char *) key_len, 2, offs);

                keylen = tsk_getu16(fs->endian, key_len);
                keylen -= 6;
                offs += 8;

                tsk_fs_read_random(fs, (char *) ucs_fn, keylen, offs);

                hfs_uni2ascii(fs, (char *) ucs_fn, keylen / 2,
                    fs_dent->name, HFS_MAXNAMLEN);

                fs_inode = fs->inode_lookup(fs, newinum);

                filetype = tsk_getu16(fs->endian, hfs->cat->rec_type);

                if (filetype == HFS_FOLDER_RECORD)
                    fs_dent->ent_type = TSK_FS_DENT_TYPE_DIR;
                else
                    fs_dent->ent_type = TSK_FS_DENT_TYPE_REG;

                fs_dent->flags = TSK_FS_DENT_FLAG_ALLOC;

                if ((flags & fs_dent->flags) == fs_dent->flags) {

                    if (TSK_WALK_STOP == action(fs, fs_dent, ptr)) {
                        tsk_fs_dent_free(fs_dent);
                        return 0;
                    }
                }

                if (filetype == HFS_FOLDER_RECORD) {
                    if (flags & TSK_FS_DENT_FLAG_RECURSE) {
                        if (dinfo->depth < MAX_DEPTH) {
                            dinfo->didx[dinfo->depth] =
                                &dinfo->dirs[strlen(dinfo->dirs)];
                            strncpy(dinfo->didx[dinfo->depth],
                                fs_dent->name,
                                DIR_STRSZ - strlen(dinfo->dirs));
                            strncat(dinfo->dirs, "/", DIR_STRSZ);
                        }
                        dinfo->depth++;

                        hfs_dent_walk_lcl(fs, dinfo, newinum, flags,
                            action, ptr);
                        dinfo->depth--;

                        if (dinfo->depth < MAX_DEPTH)
                            *dinfo->didx[dinfo->depth] = '\0';
                    }
                }



            }
        }

        /* regular file */
    }
    else {

        fs_dent->inode = inum;
        offs = hfs->key;
        tsk_fs_read_random(fs, (char *) key_len, 2, offs);
        keylen = tsk_getu16(fs->endian, key_len);

        /* skip key length and parent cnid fields */
        keylen -= 6;
        offs += 8;

        tsk_fs_read_random(fs, (char *) ucs_fn, keylen, offs);

        hfs_uni2ascii(fs, (char *) ucs_fn, keylen / 2, fs_dent->name,
            HFS_MAXNAMLEN);

        fs_dent->path = dinfo->dirs;
        fs_dent->pathdepth = dinfo->depth;
        fs_dent->fsi = fs->inode_lookup(fs, fs_dent->inode);

        fs_dent->ent_type = TSK_FS_DENT_TYPE_REG;
        fs_dent->flags = TSK_FS_DENT_FLAG_ALLOC;

        if (TSK_WALK_STOP == action(fs, fs_dent, ptr)) {
            tsk_fs_dent_free(fs_dent);
            return 0;
        }
    }

    return 0;
}