Ejemplo n.º 1
0
/* msdos_file_open --
 *     Open fat-file which correspondes to the file
 *
 * PARAMETERS:
 *     iop        - file control block
 *     pathname   - name
 *     flag       - flags
 *     mode       - mode
 *
 * RETURNS:
 *     RC_OK, if file opened successfully, or -1 if error occured
 *     and errno set appropriately
 */
int
msdos_file_open(rtems_libio_t *iop, const char *pathname, uint32_t   flag,
                uint32_t   mode)
{
    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);

    rc = fat_file_reopen(fat_fd);
    if (rc != RC_OK)
    {
        rtems_semaphore_release(fs_info->vol_sema);
        return rc;
    }

    if (iop->flags & LIBIO_FLAGS_APPEND)
        iop->offset = fat_fd->fat_file_size;

    iop->size = fat_fd->fat_file_size;

    rtems_semaphore_release(fs_info->vol_sema);
    return RC_OK;
}
Ejemplo n.º 2
0
static int msdos_clone_node_info(rtems_filesystem_location_info_t *loc)
{
    fat_file_fd_t *fat_fd = loc->node_access;

    return fat_file_reopen(fat_fd);
}
/* 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;
}