diff options
Diffstat (limited to 'cpukit/libfs/src/dosfs/msdos_eval.c')
-rw-r--r-- | cpukit/libfs/src/dosfs/msdos_eval.c | 416 |
1 files changed, 45 insertions, 371 deletions
diff --git a/cpukit/libfs/src/dosfs/msdos_eval.c b/cpukit/libfs/src/dosfs/msdos_eval.c index 9b5e0c835d..0ab5971e62 100644 --- a/cpukit/libfs/src/dosfs/msdos_eval.c +++ b/cpukit/libfs/src/dosfs/msdos_eval.c @@ -52,384 +52,58 @@ msdos_set_handlers(rtems_filesystem_location_info_t *loc) 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, - size_t pathnamelen, - int flags, - rtems_filesystem_location_info_t *pathloc - ) +static bool msdos_is_directory( + rtems_filesystem_eval_path_context_t *ctx, + void *arg +) { - 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; - } + rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_get_currentloc( ctx ); + fat_file_fd_t *fat_fd = currentloc->node_access; - /* - * Am I at the root of this mounted filesystem? - */ - if (rtems_filesystem_is_root_location(pathloc)) - { - /* - * 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; + return fat_fd->fat_file_type == MSDOS_DIRECTORY; } -/* 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 - ) +static rtems_filesystem_eval_path_generic_status msdos_eval_token( + rtems_filesystem_eval_path_context_t *ctx, + void *arg, + const char *token, + size_t tokenlen +) { - 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; + rtems_filesystem_eval_path_generic_status status = + RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE; + + if (rtems_filesystem_is_current_directory(token, tokenlen)) { + rtems_filesystem_eval_path_clear_token(ctx); + status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE; + } else { + rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_get_currentloc(ctx); + int rc = msdos_find_name(currentloc, token, tokenlen); + + if (rc == RC_OK) { + rtems_filesystem_eval_path_clear_token(ctx); + msdos_set_handlers(currentloc); + if (rtems_filesystem_eval_path_has_path(ctx)) { + status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE; + } + } else if (rc == MSDOS_NAME_NOT_FOUND_ERR) { + status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY; + } else { + rtems_filesystem_eval_path_error(ctx, 0); } + } - 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 (rtems_filesystem_is_root_location(pathloc)) - { - /* - * 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; + return status; +} -error: - fat_file_close(pathloc->mt_entry, fat_fd); +static const rtems_filesystem_eval_path_generic_config msdos_eval_config = { + .is_directory = msdos_is_directory, + .eval_token = msdos_eval_token +}; -err: - rtems_semaphore_release(fs_info->vol_sema); - return rc; +void msdos_eval_path(rtems_filesystem_eval_path_context_t *ctx) +{ + rtems_filesystem_eval_path_generic(ctx, NULL, &msdos_eval_config); } |