Esempio n. 1
0
/**
 * Utility method to help determine if a file is a FAT file system file (such as $MBR).
 *
 * @returns 1 if the file is an FAT System file, 0 if not.
 */
uint8_t
TskAuto::isFATSystemFiles(TSK_FS_FILE * a_fs_file)
{
    if ((a_fs_file) && (a_fs_file->fs_info)
        && (TSK_FS_TYPE_ISFAT(a_fs_file->fs_info->ftype))
        && (a_fs_file->name->meta_addr == FATFS_MBRINO(a_fs_file->fs_info)
            || a_fs_file->name->meta_addr ==
            FATFS_FAT1INO(a_fs_file->fs_info)
            || a_fs_file->name->meta_addr ==
            FATFS_FAT2INO(a_fs_file->fs_info)))
        return 1;
    else
        return 0;
}
TSK_RETVAL_ENUM
fatfs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,
    TSK_INUM_T a_addr)
{
    TSK_OFF_T size, len;
    FATFS_INFO *fatfs = (FATFS_INFO *) a_fs;
    char *dirbuf;
    TSK_DADDR_T *addrbuf;
    FATFS_LOAD_DIR load;
    int retval;

    TSK_FS_DIR *fs_dir;

    if ((a_addr < a_fs->first_inum) || (a_addr > a_fs->last_inum)) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_WALK_RNG);
        tsk_error_set_errstr("fatfs_dir_open_meta: invalid a_addr value: %"
            PRIuINUM "\n", a_addr);
        return TSK_ERR;
    }
    else if (a_fs_dir == NULL) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_ARG);
        tsk_error_set_errstr
            ("fatfs_dir_open_meta: NULL fs_attr argument given");
        return TSK_ERR;
    }

    fs_dir = *a_fs_dir;
    if (fs_dir) {
        tsk_fs_dir_reset(fs_dir);
    }
    else {
        if ((*a_fs_dir = fs_dir =
                tsk_fs_dir_alloc(a_fs, a_addr, 128)) == NULL) {
            return TSK_ERR;
        }
    }

    //  handle the orphan directory if its contents were requested
    if (a_addr == TSK_FS_ORPHANDIR_INUM(a_fs)) {
        return tsk_fs_dir_find_orphans(a_fs, fs_dir);
    }

    fs_dir->fs_file = tsk_fs_file_open_meta(a_fs, NULL, a_addr);
    if (fs_dir->fs_file == NULL) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_INODE_NUM);
        tsk_error_set_errstr("fatfs_dir_open_meta: %" PRIuINUM
            " is not a valid inode", a_addr);
        return TSK_COR;
    }

    size = fs_dir->fs_file->meta->size;
    len = roundup(size, fatfs->ssize);

    if (tsk_verbose)
        tsk_fprintf(stderr,
            "fatfs_dir_open_meta: Processing directory %" PRIuINUM "\n",
            a_addr);

    if (size == 0) {
        if (tsk_verbose)
            tsk_fprintf(stderr,
                "fatfs_dir_open_meta: directory has 0 size\n");
        return TSK_OK;
    }

    /* Make a copy of the directory contents using file_walk */
    if ((dirbuf = tsk_malloc((size_t) len)) == NULL) {
        return TSK_ERR;
    }
    load.curdirptr = dirbuf;
    load.dirleft = (size_t) size;

    /* We are going to save the address of each sector in the directory
     * in a stack - they are needed to determine the inode address.
     */
    load.addrsize = (size_t) (len / fatfs->ssize);
    addrbuf =
        (TSK_DADDR_T *) tsk_malloc(load.addrsize * sizeof(TSK_DADDR_T));
    if (addrbuf == NULL) {
        free(dirbuf);
        return TSK_ERR;
    }

    /* Set the variables that are used during the copy */
    load.addridx = 0;
    load.addrbuf = addrbuf;

    /* save the directory contents into dirbuf */
    if (tsk_fs_file_walk(fs_dir->fs_file,
            TSK_FS_FILE_WALK_FLAG_SLACK,
            fatfs_dent_action, (void *) &load)) {
        tsk_error_errstr2_concat("- fatfs_dir_open_meta");
        free(dirbuf);
        free(addrbuf);
        return TSK_COR;
    }

    /* We did not copy the entire directory, which occurs if an error occured */
    if (load.dirleft > 0) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_FWALK);
        tsk_error_set_errstr
            ("fatfs_dir_open_meta: Error reading directory %" PRIuINUM,
            a_addr);

        /* Free the local buffers */
        free(dirbuf);
        free(addrbuf);
        return TSK_COR;
    }

    if (tsk_verbose)
        fprintf(stderr,
            "fatfs_dir_open_meta: Parsing directory %" PRIuINUM "\n",
            a_addr);

    retval = fatfs_dent_parse_buf(fatfs, fs_dir, dirbuf, len, addrbuf);

    free(dirbuf);
    free(addrbuf);

    // if we are listing the root directory, add the Orphan directory and special FAT file entries
    if (a_addr == a_fs->root_inum) {
        TSK_FS_NAME *fs_name = tsk_fs_name_alloc(256, 0);
        if (fs_name == NULL)
            return TSK_ERR;

        // MBR Entry
        strncpy(fs_name->name, FATFS_MBRNAME, fs_name->name_size);
        fs_name->meta_addr = FATFS_MBRINO(a_fs);
        fs_name->type = TSK_FS_NAME_TYPE_VIRT;
        fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;
        if (tsk_fs_dir_add(fs_dir, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }

        // FAT1 Entry
        strncpy(fs_name->name, FATFS_FAT1NAME, fs_name->name_size);
        fs_name->meta_addr = FATFS_FAT1INO(a_fs);
        fs_name->type = TSK_FS_NAME_TYPE_VIRT;
        fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;
        if (tsk_fs_dir_add(fs_dir, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }

        // FAT2 Entry
        strncpy(fs_name->name, FATFS_FAT2NAME, fs_name->name_size);
        fs_name->meta_addr = FATFS_FAT2INO(a_fs);
        fs_name->type = TSK_FS_NAME_TYPE_VIRT;
        fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;
        if (tsk_fs_dir_add(fs_dir, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }

        // orphan directory
        if (tsk_fs_dir_make_orphan_dir_name(a_fs, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }
        if (tsk_fs_dir_add(fs_dir, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }
        tsk_fs_name_free(fs_name);
    }

    return retval;
}