From f36a7bfcde756cae3b3e933f0e688137fb684be8 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Thu, 28 Feb 2002 20:43:50 +0000 Subject: 2002-02-28 Victor V. Vengerov * DOS filesystem including FAT12, FAT16, and FAT32 support submitted. * src/dosfs, src/dosfs/Makefile.am, src/dosfs/stamp-h2.in, src/dosfs/config.h.in, src/dosfs/dosfs.h, src/dosfs/fat.c, src/dosfs/fat.h, src/dosfs/fat_fat_operations.c, src/dosfs/fat_fat_operations.h, src/dosfs/fat_file.c, src/dosfs/fat_file.h, src/dosfs/msdos.h, src/dosfs/msdos_create.c, src/dosfs/msdos_dir.c, src/dosfs/msdos_eval.c, src/dosfs/msdos_file.c, src/dosfs/msdos_free.c, src/dosfs/msdos_fsunmount.c, src/dosfs/msdos_handlers_dir.c, src/dosfs/msdos_handlers_file.c, src/dosfs/msdos_init.c, src/dosfs/msdos_initsupp.c, src/dosfs/msdos_misc.c, src/dosfs/msdos_mknod.c, src/dosfs/msdos_node_type.c, src/dosfs/.cvsignore: New files. * configure.ac, src/Makefile.am, wrapup/Makefile.am: Modified to reflect addition. --- cpukit/libfs/src/dosfs/msdos_eval.c | 435 ++++++++++++++++++++++++++++++++++++ 1 file changed, 435 insertions(+) create mode 100644 cpukit/libfs/src/dosfs/msdos_eval.c (limited to 'cpukit/libfs/src/dosfs/msdos_eval.c') diff --git a/cpukit/libfs/src/dosfs/msdos_eval.c b/cpukit/libfs/src/dosfs/msdos_eval.c new file mode 100644 index 0000000000..3eba0e63e8 --- /dev/null +++ b/cpukit/libfs/src/dosfs/msdos_eval.c @@ -0,0 +1,435 @@ +/* + * MSDOS evaluation routines + * + * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia + * Author: Eugeny S. Mints + * + * 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. + * + * @(#) $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +#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; +} -- cgit v1.2.3