Exemplo n.º 1
0
/* msdos_free_node_info --
 *     Call fat-file close routine.
 *
 * PARAMETERS:
 *     pathloc - node description
 *
 * RETURNS:
 *     RC_OK on success, or -1 code if error occured
 *
 */
int
msdos_free_node_info(rtems_filesystem_location_info_t *pathloc)
{
    int                rc = RC_OK;
    rtems_status_code  sc = RTEMS_SUCCESSFUL;
    msdos_fs_info_t   *fs_info = pathloc->mt_entry->fs_info;

    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
    if (sc != RTEMS_SUCCESSFUL)
        rtems_set_errno_and_return_minus_one(EIO);

    rc = fat_file_close(pathloc->mt_entry, pathloc->node_access);

    rtems_semaphore_release(fs_info->vol_sema);
    return rc;
}
Exemplo n.º 2
0
/* msdos_file_close --
 *     Close fat-file which correspondes to the file. If fat-file descriptor
 *     which correspondes to the file is not marked "removed", synchronize
 *     size, first cluster number, write time and date fields of the file.
 *
 * PARAMETERS:
 *     iop - file control block
 *
 * RETURNS:
 *     RC_OK, if file closed successfully, or -1 if error occured (errno set
 *     appropriately)
 */
int
msdos_file_close(rtems_libio_t *iop)
{
    int                rc = RC_OK;
    rtems_status_code  sc = RTEMS_SUCCESSFUL;
    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
    fat_file_fd_t     *fat_fd = iop->pathinfo.node_access;

    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
    if (sc != RTEMS_SUCCESSFUL)
        rtems_set_errno_and_return_minus_one(EIO);

    /*
     * if fat-file descriptor is not marked as "removed", synchronize
     * size, first cluster number, write time and date fields of the file
     */
    if (!FAT_FILE_IS_REMOVED(fat_fd))
    {
        rc = msdos_set_first_cluster_num(iop->pathinfo.mt_entry, fat_fd);
        if (rc != RC_OK)
        {
            rtems_semaphore_release(fs_info->vol_sema);
            return rc;
        }

        rc = msdos_set_file_size(iop->pathinfo.mt_entry, fat_fd);
        if (rc != RC_OK)
        {
            rtems_semaphore_release(fs_info->vol_sema);
            return rc;
        }

        rc = msdos_set_dir_wrt_time_and_date(iop->pathinfo.mt_entry, fat_fd);
        if (rc != RC_OK)
        {
            rtems_semaphore_release(fs_info->vol_sema);
            return rc;
        }
    }

    rc = fat_file_close(iop->pathinfo.mt_entry, fat_fd);

    rtems_semaphore_release(fs_info->vol_sema);
    return rc;
}
Exemplo n.º 3
0
/* msdos_get_dotdot_dir_info_cluster_num_and_offset --
 *     Get cluster num and offset not of ".." slot, but slot which correspondes
 *     to real directory name.
 *
 * PARAMETERS:
 *     mt_entry       - mount table entry
 *     cln            - data cluster num extracted drom ".." slot
 *     paux           - identify a node location on the disk -
 *                      number of cluster and offset inside the cluster
 *     dir_entry      - placeholder for found node
 *
 * RETURNS:
 *     RC_OK, filled 'paux' and 'dir_entry' on success, or -1 if error occured
 *     (errno set apropriately)
 *
 */
int
msdos_get_dotdot_dir_info_cluster_num_and_offset(
    rtems_filesystem_mount_table_entry_t *mt_entry,
    uint32_t                              cln,
    fat_auxiliary_t                      *paux,
    char                                 *dir_entry
    )
{
    int              rc = RC_OK;
    msdos_fs_info_t *fs_info = mt_entry->fs_info;
    fat_file_fd_t   *fat_fd = NULL;
    char             dot_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
    char             dotdot_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
    uint32_t         cl4find = 0;

    memset(dot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
    memset(dotdot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);

    /*
     * open fat-file corresponded to ".."
     */
    rc = fat_file_open(mt_entry, paux->cln, paux->ofs, &fat_fd);
    if (rc != RC_OK)
        return rc;

    fat_fd->info_cln = paux->cln;
    fat_fd->info_ofs = paux->ofs;
    fat_fd->cln = cln;
    fat_fd->fat_file_type = FAT_DIRECTORY;
    fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;

    fat_fd->map.file_cln = 0;
    fat_fd->map.disk_cln = fat_fd->cln;

    rc = fat_file_size(mt_entry, fat_fd);
    if (rc != RC_OK)
    {
        fat_file_close(mt_entry, fat_fd);
        return rc;
    }

    /* find "." node in opened directory */
    rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, MSDOS_DOT_NAME, paux,
                                     dot_node);

    if (rc != RC_OK)
    {
        fat_file_close(mt_entry, fat_fd);
        return rc;
    }

    /* find ".." node in opened directory */
    rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, MSDOS_DOTDOT_NAME, paux,
                                     dotdot_node);

    if (rc != RC_OK)
    {
        fat_file_close(mt_entry, fat_fd);
        return rc;
    }

    cl4find = MSDOS_EXTRACT_CLUSTER_NUM(dot_node);

    /* close fat-file corresponded to ".." directory */
    rc = fat_file_close(mt_entry, fat_fd);
    if ( rc != RC_OK )
        return rc;

    if ( (MSDOS_EXTRACT_CLUSTER_NUM(dotdot_node)) == 0)
    {
        /*
         * we handle root dir for all FAT types in the same way with the
         * ordinary directories ( through fat_file_* calls )
         */
        paux->cln = FAT_ROOTDIR_CLUSTER_NUM;
        paux->ofs = 0;
    }

    /* open fat-file corresponded to second ".." */
    rc = fat_file_open(mt_entry, paux->cln, paux->ofs, &fat_fd);
    if (rc != RC_OK)
        return rc;

    fat_fd->info_cln = paux->cln;
    fat_fd->info_ofs = paux->ofs;

    if ((MSDOS_EXTRACT_CLUSTER_NUM(dotdot_node)) == 0)
        fat_fd->cln = fs_info->fat.vol.rdir_cl;
    else
        fat_fd->cln = MSDOS_EXTRACT_CLUSTER_NUM(dotdot_node);

    fat_fd->fat_file_type = FAT_DIRECTORY;
    fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;

    fat_fd->map.file_cln = 0;
    fat_fd->map.disk_cln = fat_fd->cln;

    rc = fat_file_size(mt_entry, fat_fd);
    if (rc != RC_OK)
    {
        fat_file_close(mt_entry, fat_fd);
        return rc;
    }

    /* in this directory find slot with specified cluster num */
    rc = msdos_find_node_by_cluster_num_in_fat_file(mt_entry, fat_fd, cl4find,
                                                    paux, dir_entry);
    if (rc != RC_OK)
    {
        fat_file_close(mt_entry, fat_fd);
        return rc;
    }
    rc = fat_file_close(mt_entry, fat_fd);
    return rc;
}
Exemplo n.º 4
0
/* msdos_find_name --
 *     Find the node which correspondes to the name, open fat-file which
 *     correspondes to the found node and close fat-file which correspondes
 *     to the node we searched in.
 *
 * PARAMETERS:
 *     parent_loc - parent node description
 *     name       - name to find
 *
 * RETURNS:
 *     RC_OK and updated 'parent_loc' on success, or -1 if error
 *     occured (errno set apropriately)
 *
 */
int
msdos_find_name(
    rtems_filesystem_location_info_t *parent_loc,
    char                             *name
    )
{
    int              rc = RC_OK;
    msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
    fat_file_fd_t   *fat_fd = NULL;
    fat_auxiliary_t  aux;
    unsigned short   time_val = 0;
    unsigned short   date = 0;
    char             node_entry[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];

    memset(node_entry, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);

    /*
     * find the node which correspondes to the name in the directory pointed by
     * 'parent_loc'
     */
    rc = msdos_get_name_node(parent_loc, name, &aux, node_entry);
    if (rc != RC_OK)
        return rc;

    /* open fat-file corresponded to the found node */
    rc = fat_file_open(parent_loc->mt_entry, aux.cln, aux.ofs, &fat_fd);
    if (rc != RC_OK)
        return rc;

    /*
     * I don't like this if, but: we should do it , or should write new file
     * size and first cluster num to the disk after each write operation
     * (even if one byte is written  - that is TOO non-optimize) because
     * otherwise real values of these fields stored in fat-file descriptor
     * may be accidentely rewritten with wrong values stored on the disk
     */
    if (fat_fd->links_num == 1)
    {
        fat_fd->info_cln = aux.cln;
        fat_fd->info_ofs = aux.ofs;
        fat_fd->cln = MSDOS_EXTRACT_CLUSTER_NUM(node_entry);
        fat_fd->first_char = *MSDOS_DIR_NAME(node_entry);

        time_val = *MSDOS_DIR_WRITE_TIME(node_entry);
        date = *MSDOS_DIR_WRITE_DATE(node_entry);

        fat_fd->mtime = msdos_date_dos2unix(CF_LE_W(time_val), CF_LE_W(date));

        if ((*MSDOS_DIR_ATTR(node_entry)) & MSDOS_ATTR_DIRECTORY)
        {
            fat_fd->fat_file_type = FAT_DIRECTORY;
            fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;

            rc = fat_file_size(parent_loc->mt_entry, fat_fd);
            if (rc != RC_OK)
            {
                fat_file_close(parent_loc->mt_entry, fat_fd);
                return rc;
            }
        }
        else
        {
            fat_fd->fat_file_size = CF_LE_L(*MSDOS_DIR_FILE_SIZE(node_entry));
            fat_fd->fat_file_type = FAT_FILE;
            fat_fd->size_limit = MSDOS_MAX_FILE_SIZE;
        }

        /* these data is not actual for zero-length fat-file */
        fat_fd->map.file_cln = 0;
        fat_fd->map.disk_cln = fat_fd->cln;

        if ((fat_fd->fat_file_size != 0) &&
            (fat_fd->fat_file_size <= fs_info->fat.vol.bpc))
        {
            fat_fd->map.last_cln = fat_fd->cln;
        }
        else
        {
            fat_fd->map.last_cln = FAT_UNDEFINED_VALUE;
        }
    }

    /* close fat-file corresponded to the node we searched in */
    rc = fat_file_close(parent_loc->mt_entry, parent_loc->node_access);
    if (rc != RC_OK)
    {
        fat_file_close(parent_loc->mt_entry, fat_fd);
        return rc;
    }

    /* update node_info_ptr field */
    parent_loc->node_access = fat_fd;

    return rc;
}
/* msdos_eval_path --
 *
 *     The following routine evaluate path for a node that wishes to be
 *     accessed.  Structure 'pathloc' is returned with a pointer to the
 *     node to be accessed.
 *
 * PARAMETERS:
 *     pathname - path for evaluation
 *     flags    - flags
 *     pathloc  - node description (IN/OUT)
 *
 * RETURNS:
 *     RC_OK and filled pathloc on success, or -1 if error occured
 *     (errno set appropriately)
 *
 */
int
msdos_eval_path(
    const char                        *pathname,
    size_t                             pathnamelen,
    int                                flags,
    rtems_filesystem_location_info_t  *pathloc
    )
{
    int                               rc = RC_OK;
    rtems_status_code                 sc = RTEMS_SUCCESSFUL;
    msdos_fs_info_t                  *fs_info = pathloc->mt_entry->fs_info;
    fat_file_fd_t                    *fat_fd = NULL;
    rtems_filesystem_location_info_t  newloc;
    int                               i = 0;
    int                               token_len = 0;
    msdos_token_types_t               type = MSDOS_CURRENT_DIR;
    const char                       *token;

    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
    if (sc != RTEMS_SUCCESSFUL)
        rtems_set_errno_and_return_minus_one(EIO);

    if (!pathloc->node_access)
    {
        errno = ENOENT;
        rc = -1;
        goto err;
    }

    fat_fd = pathloc->node_access;

    rc = fat_file_reopen(fat_fd);
    if (rc != RC_OK)
        goto err;

    while ((type != MSDOS_NO_MORE_PATH) && (type != MSDOS_INVALID_TOKEN))
    {
        type = msdos_get_token(&pathname[i], pathnamelen, &token, &token_len);
        pathnamelen -= token_len;
        i += token_len;

        fat_fd = pathloc->node_access;

        switch (type)
        {
            case MSDOS_UP_DIR:
                /*
                 *  Only a directory can be decended into.
                 */
                if (fat_fd->fat_file_type != FAT_DIRECTORY)
                {
                    errno = ENOTSUP;
                    rc = -1;
                    goto error;
                }

                /*
                 *  Am I at the root of this mounted filesystem?
                 */
                if (pathloc->node_access ==
                    pathloc->mt_entry->mt_fs_root.node_access)
                {
                    /*
                     *  Am I at the root of all filesystems?
                     *  XXX: MSDOS is not supposed to be base fs.
                     */
                    if (pathloc->node_access ==
                        rtems_filesystem_root.node_access)
                    {
                        break;       /* Throw out the .. in this case */
                    }
                    else
                    {
                        newloc = pathloc->mt_entry->mt_point_node;
                        *pathloc = newloc;

                        rc = fat_file_close(pathloc->mt_entry, fat_fd);
                        if (rc != RC_OK)
                            goto err;

                        rtems_semaphore_release(fs_info->vol_sema);
                        return (*pathloc->ops->evalpath_h)(&(pathname[i-token_len]),
                                                           pathnamelen + token_len,
                                                           flags, pathloc);
                    }
                }
                else
                {
                  rc = msdos_find_name(pathloc, token, token_len);
                    if (rc != RC_OK)
                    {
                        if (rc == MSDOS_NAME_NOT_FOUND_ERR)
                        {
                            errno = ENOENT;
                            rc = -1;
                        }
                        goto error;
                    }
                }
                break;

            case MSDOS_NAME:
                /*
                 *  Only a directory can be decended into.
                 */
                if (fat_fd->fat_file_type != FAT_DIRECTORY)
                {
                    errno = ENOTSUP;
                    rc = -1;
                    goto error;
                }

                /*
                 *  Otherwise find the token name in the present location and
                 * set the node access to the point we have found.
                 */
                rc = msdos_find_name(pathloc, token, token_len);
                if (rc != RC_OK)
                {
                    if (rc == MSDOS_NAME_NOT_FOUND_ERR)
                    {
                        errno = ENOENT;
                        rc = -1;
                    }
                    goto error;
                }
                break;

            case MSDOS_NO_MORE_PATH:
            case MSDOS_CURRENT_DIR:
                break;

            case MSDOS_INVALID_TOKEN:
                errno = ENAMETOOLONG;
                rc = -1;
                goto error;
                break;

        }
    }

    /*
     *  Always return the root node.
     *
     *  If we are at a node that is a mount point. Set loc to the
     *  new fs root node and let let the mounted filesystem set the handlers.
     *
     *  NOTE: The behavior of stat() on a mount point appears to be
     *        questionable.
     *  NOTE: MSDOS filesystem currently doesn't support mount functionality ->
     *        action not implemented
     */
    fat_fd = pathloc->node_access;

    msdos_set_handlers(pathloc);

    rtems_semaphore_release(fs_info->vol_sema);
    return RC_OK;

error:
    fat_file_close(pathloc->mt_entry, fat_fd);

err:
    rtems_semaphore_release(fs_info->vol_sema);
    return rc;
}
/* msdos_eval4make --
 *     The following routine evaluate path for a new node to be created.
 *     'pathloc' is returned with a pointer to the parent of the new node.
 *     'name' is returned with a pointer to the first character in the
 *     new node name.  The parent node is verified to be a directory.
 *
 * PARAMETERS:
 *     path    - path for evaluation
 *     pathloc - IN/OUT (start point for evaluation/parent directory for
 *               creation)
 *     name    - new node name
 *
 * RETURNS:
 *     RC_OK, filled pathloc for parent directory and name of new node on
 *     success, or -1 if error occured (errno set appropriately)
 */
int
msdos_eval4make(
    const char                         *path,
    rtems_filesystem_location_info_t   *pathloc,
    const char                        **name
    )
{
    int                               rc = RC_OK;
    rtems_status_code                 sc = RTEMS_SUCCESSFUL;
    msdos_fs_info_t                  *fs_info = pathloc->mt_entry->fs_info;
    fat_file_fd_t                    *fat_fd = NULL;
    rtems_filesystem_location_info_t  newloc;
    msdos_token_types_t               type;
    int                               i = 0;
    int                               token_len;
    const char                       *token;
    bool                              done = false;

    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
    if (sc != RTEMS_SUCCESSFUL)
        rtems_set_errno_and_return_minus_one(EIO);

    if (!pathloc->node_access)
    {
        errno = ENOENT;
        rc = -1;
        goto err;
    }

    fat_fd = pathloc->node_access;

    rc = fat_file_reopen(fat_fd);
    if (rc != RC_OK)
        goto err;

    while (!done)
    {
        type = msdos_get_token(&path[i], strlen(&path[i]), &token, &token_len);
        i += token_len;
        fat_fd = pathloc->node_access;

        switch (type)
        {
            case MSDOS_UP_DIR:
                /*
                 *  Only a directory can be decended into.
                 */
                if (fat_fd->fat_file_type != FAT_DIRECTORY)
                {
                    errno = ENOTDIR;
                    rc = -1;
                    goto error;
                }

                /*
                 *  Am I at the root of this mounted filesystem?
                 */
                if (pathloc->node_access ==
                    pathloc->mt_entry->mt_fs_root.node_access)
                {
                    /*
                     *  Am I at the root of all filesystems?
                     *  XXX: MSDOS is not supposed to be base fs.
                     */
                    if (pathloc->node_access ==
                        rtems_filesystem_root.node_access)
                    {
                        break;       /* Throw out the .. in this case */
                    }
                    else
                    {
                        newloc = pathloc->mt_entry->mt_point_node;
                        *pathloc = newloc;

                        rc = fat_file_close(pathloc->mt_entry, fat_fd);
                        if (rc != RC_OK)
                            goto err;

                        rtems_semaphore_release(fs_info->vol_sema);
                        return (*pathloc->ops->evalformake_h)(&path[i-token_len],
                                                              pathloc, name);
                    }
                }
                else
                {
                    rc = msdos_find_name(pathloc, token, token_len);
                    if (rc != RC_OK)
                    {
                        if (rc == MSDOS_NAME_NOT_FOUND_ERR)
                        {
                            errno = ENOENT;
                            rc = -1;
                        }
                        goto error;
                    }
                }
                break;

            case MSDOS_NAME:
                /*
                 *  Only a directory can be decended into.
                 */
                if (fat_fd->fat_file_type != FAT_DIRECTORY)
                {
                    errno = ENOTDIR;
                    rc = -1;
                    goto error;
                }

                /*
                 * Otherwise find the token name in the present location and
                 * set the node access to the point we have found.
                 */
                rc = msdos_find_name(pathloc, token, token_len);
                if (rc)
                {
                    if (rc != MSDOS_NAME_NOT_FOUND_ERR)
                    {
                        errno = ENOENT;
                        rc = -1;
                        goto error;
                    }
                    else
                        done = true;
                }
                break;

            case MSDOS_NO_MORE_PATH:
                errno = EEXIST;
                rc = -1;
                goto error;
                break;

            case MSDOS_CURRENT_DIR:
                break;

            case MSDOS_INVALID_TOKEN:
                errno = ENAMETOOLONG;
                rc = -1;
                goto error;
                break;

        }
    }

    *name = &path[i - token_len];

    /*
     * We have evaluated the path as far as we can.
     * Verify there is not any invalid stuff at the end of the name.
     */
    for( ; path[i] != '\0'; i++)
    {
        if (!msdos_is_separator(path[i]))
        {
            errno = ENOENT;
            rc = -1;
            goto error;
        }
    }

    fat_fd = pathloc->node_access;

    if (fat_fd->fat_file_type != FAT_DIRECTORY)
    {
        errno = ENOTDIR;
        rc = -1;
        goto error;
    }

    msdos_set_handlers(pathloc);

    rtems_semaphore_release(fs_info->vol_sema);
    return RC_OK;

error:
    fat_file_close(pathloc->mt_entry, fat_fd);

err:
    rtems_semaphore_release(fs_info->vol_sema);
    return rc;
}
Exemplo n.º 7
0
static int fat32fs_closedir(vfs_fd *vfd) {
	if (!vfd->private_data)
		return -1;
	return fat_file_close((fat_file *)vfd->private_data);
}
Exemplo n.º 8
0
/* msdos_initialize_support --
 *     MSDOS filesystem initialization
 *
 * PARAMETERS:
 *     temp_mt_entry      - mount table entry
 *     op_table           - filesystem operations table
 *     file_handlers      - file operations table
 *     directory_handlers - directory operations table
 *
 * RETURNS:
 *     RC_OK and filled temp_mt_entry on success, or -1 if error occured
 *     (errno set apropriately)
 *
 */
int
msdos_initialize_support(
    rtems_filesystem_mount_table_entry_t    *temp_mt_entry,
    const rtems_filesystem_operations_table *op_table,
    const rtems_filesystem_file_handlers_r  *file_handlers,
    const rtems_filesystem_file_handlers_r  *directory_handlers,
    rtems_dosfs_convert_control             *converter
    )
{
    int                rc = RC_OK;
    rtems_status_code  sc = RTEMS_SUCCESSFUL;
    msdos_fs_info_t   *fs_info = NULL;
    fat_file_fd_t     *fat_fd = NULL;
    fat_dir_pos_t      root_pos;
    uint32_t           cl_buf_size;

    fs_info = (msdos_fs_info_t *)calloc(1, sizeof(msdos_fs_info_t));
    if (!fs_info)
        rtems_set_errno_and_return_minus_one(ENOMEM);

    temp_mt_entry->fs_info = fs_info;

    fs_info->converter = converter;

    rc = fat_init_volume_info(&fs_info->fat, temp_mt_entry->dev);
    if (rc != RC_OK)
    {
        free(fs_info);
        return rc;
    }

    fs_info->file_handlers      = file_handlers;
    fs_info->directory_handlers = directory_handlers;

    /*
     * open fat-file which correspondes to  root directory
     * (so inode number 0x00000010 is always used for root directory)
     */
    fat_dir_pos_init(&root_pos);
    root_pos.sname.cln = FAT_ROOTDIR_CLUSTER_NUM;
    rc = fat_file_open(&fs_info->fat, &root_pos, &fat_fd);
    if (rc != RC_OK)
    {
        fat_shutdown_drive(&fs_info->fat);
        free(fs_info);
        return rc;
    }

    /* again: unfortunately "fat-file" is just almost fat file :( */
    fat_fd->fat_file_type = FAT_DIRECTORY;
    fat_fd->size_limit = MSDOS_MAX_DIR_LENGTH;
    fat_fd->cln = fs_info->fat.vol.rdir_cl;

    fat_fd->map.file_cln = 0;
    fat_fd->map.disk_cln = fat_fd->cln;

    /* if we have FAT12/16 */
    if ( fat_fd->cln == 0 )
    {
        fat_fd->fat_file_size = fs_info->fat.vol.rdir_size;
        cl_buf_size = (fs_info->fat.vol.bpc > fs_info->fat.vol.rdir_size) ?
                      fs_info->fat.vol.bpc                                :
                      fs_info->fat.vol.rdir_size;
    }
    else
    {
        rc = fat_file_size(&fs_info->fat, fat_fd);
        if ( rc != RC_OK )
        {
            fat_file_close(&fs_info->fat, fat_fd);
            fat_shutdown_drive(&fs_info->fat);
            free(fs_info);
            return rc;
        }
        cl_buf_size = fs_info->fat.vol.bpc;
    }

    fs_info->cl_buf = (uint8_t *)calloc(cl_buf_size, sizeof(char));
    if (fs_info->cl_buf == NULL)
    {
        fat_file_close(&fs_info->fat, fat_fd);
        fat_shutdown_drive(&fs_info->fat);
        free(fs_info);
        rtems_set_errno_and_return_minus_one(ENOMEM);
    }

    sc = rtems_semaphore_create(3,
                                1,
                                RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY |
                                RTEMS_INHERIT_PRIORITY,
                                0,
                                &fs_info->vol_sema);
    if (sc != RTEMS_SUCCESSFUL)
    {
        fat_file_close(&fs_info->fat, fat_fd);
        fat_shutdown_drive(&fs_info->fat);
        free(fs_info->cl_buf);
        free(fs_info);
        rtems_set_errno_and_return_minus_one( EIO );
    }

    temp_mt_entry->mt_fs_root->location.node_access = fat_fd;
    temp_mt_entry->mt_fs_root->location.handlers = directory_handlers;
    temp_mt_entry->ops = op_table;

    return rc;
}