OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [cpukit/] [libfs/] [src/] [dosfs/] [msdos_eval.c] - Rev 1765

Compare with Previous | Blame | View Log

/*
 *  MSDOS evaluation routines
 *
 *  Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
 *  Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.OARcorp.com/rtems/license.html.
 *
 *  @(#) msdos_eval.c,v 1.1 2002/02/28 20:43:50 joel Exp
 */
 
#if HAVE_CONFIG_H
#include "config.h"
#endif
 
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <assert.h>
 
#include <rtems/libio_.h>
 
#include "fat.h"
#include "fat_fat_operations.h"
#include "fat_file.h"
 
#include "msdos.h"
 
/* msdos_set_handlers --
 *     Set handlers for the node with specified type(i.e. handlers for file 
 *     or directory).
 *
 * PARAMETERS:
 *     loc - node description
 *
 * RETURNS:
 *     None
 */
static void 
msdos_set_handlers(rtems_filesystem_location_info_t *loc)
{
    msdos_fs_info_t *fs_info = loc->mt_entry->fs_info; 
    fat_file_fd_t   *fat_fd = loc->node_access;
 
    if (fat_fd->fat_file_type == FAT_DIRECTORY)
        loc->handlers = fs_info->directory_handlers;
    else
        loc->handlers = fs_info->file_handlers;
}
 
/* 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,
    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                               len = 0;
    msdos_token_types_t               type = MSDOS_CURRENT_DIR;
    char                              token[MSDOS_NAME_MAX + 1];
 
    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
    if (sc != RTEMS_SUCCESSFUL)
        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], token, &len);
        i += 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->evalpath_h)(&(pathname[i-len]),
                                                           flags, pathloc);
                    }
                } 
                else 
                {
                    rc = msdos_find_name(pathloc, token);
                    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);
                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                               len;
    char                              token[ MSDOS_NAME_MAX + 1 ];
    rtems_boolean                     done = 0;
 
    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
    if (sc != RTEMS_SUCCESSFUL)
        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], token, &len);
        i += 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-len], 
                                                              pathloc, name);
                    }
                } 
                else 
                {
                    rc = msdos_find_name(pathloc, token);
                    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);
                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 - 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; 
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.