mirror of
https://github.com/eclipse-threadx/filex.git
synced 2026-09-14 03:57:29 +08:00
937 lines
34 KiB
C
937 lines
34 KiB
C
/**************************************************************************/
|
|
/* */
|
|
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
|
/* */
|
|
/* This software is licensed under the Microsoft Software License */
|
|
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
|
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
|
/* and in the root directory of this software. */
|
|
/* */
|
|
/**************************************************************************/
|
|
|
|
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
/** */
|
|
/** FileX Component */
|
|
/** */
|
|
/** Directory */
|
|
/** */
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
|
|
#define FX_SOURCE_CODE
|
|
|
|
|
|
/* Include necessary system files. */
|
|
|
|
#include "fx_api.h"
|
|
#include "fx_system.h"
|
|
#include "fx_directory.h"
|
|
#include "fx_utility.h"
|
|
|
|
#ifndef FX_NO_LOCAL_PATH
|
|
FX_LOCAL_PATH_SETUP
|
|
#endif
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _fx_directory_search PORTABLE C */
|
|
/* 6.1.10 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* William E. Lamie, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function searches the media for the supplied name. The search */
|
|
/* routine will find files as well as directory names. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* media_ptr Media control block pointer */
|
|
/* name_ptr Name pointer */
|
|
/* entry_ptr Pointer to directory entry */
|
|
/* record */
|
|
/* last_dir_ptr Pointer to destination for */
|
|
/* the last directory entry */
|
|
/* last_name_ptr Pointer to the last name */
|
|
/* token that was searched for */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* return status */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* _fx_directory_name_extract Extract directory name from */
|
|
/* input string */
|
|
/* _fx_directory_entry_read Read entries from root dir */
|
|
/* _fx_utility_FAT_entry_read Read FAT entries to calculate */
|
|
/* the sub-directory size */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* FileX System Functions */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
|
/* 09-30-2020 William E. Lamie Modified comment(s), and */
|
|
/* added conditional to */
|
|
/* disable media search cache, */
|
|
/* resulting in version 6.1 */
|
|
/* 06-02-2021 Bhupendra Naphade Modified comment(s), and */
|
|
/* added check for */
|
|
/* volume label, */
|
|
/* resulting in version 6.1.7 */
|
|
/* 01-31-2022 William E. Lamie Modified comment(s), and */
|
|
/* fixed path compare, */
|
|
/* resulting in version 6.1.10 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _fx_directory_search(FX_MEDIA *media_ptr, CHAR *name_ptr, FX_DIR_ENTRY *entry_ptr,
|
|
FX_DIR_ENTRY *last_dir_ptr, CHAR **last_name_ptr)
|
|
{
|
|
|
|
ULONG i, n;
|
|
UINT found;
|
|
UINT status;
|
|
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
|
UINT v, j;
|
|
#endif /* FX_MEDIA_DISABLE_SEARCH_CACHE */
|
|
ULONG cluster, next_cluster = 0;
|
|
ULONG64 directory_size;
|
|
CHAR *dir_name_ptr;
|
|
CHAR *work_ptr;
|
|
CHAR *source_name_ptr;
|
|
CHAR *destination_name_ptr;
|
|
FX_DIR_ENTRY search_dir;
|
|
FX_DIR_ENTRY *search_dir_ptr;
|
|
CHAR *name, alpha, name_alpha;
|
|
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
|
UINT index;
|
|
CHAR *path_ptr = FX_NULL;
|
|
CHAR *original_name = name_ptr;
|
|
#endif
|
|
|
|
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
|
|
|
/* Increment the number of directory search requests. */
|
|
media_ptr -> fx_media_directory_searches++;
|
|
#endif
|
|
|
|
/* Setup pointer to media name buffer. */
|
|
name = media_ptr -> fx_media_name_buffer;
|
|
|
|
/* Setup the last directory, if required. */
|
|
if (last_dir_ptr)
|
|
{
|
|
|
|
/* Set the first character of the directory entry to NULL to
|
|
indicate root or no directory. */
|
|
last_dir_ptr -> fx_dir_entry_name[0] = 0;
|
|
}
|
|
|
|
/* Determine if the file name has a full directory path. */
|
|
if ((*name_ptr == '\\') || (*name_ptr == '/'))
|
|
{
|
|
|
|
/* Directory name has full path, set the search pointer to NULL. */
|
|
search_dir_ptr = FX_NULL;
|
|
}
|
|
else
|
|
{
|
|
|
|
/* Set the initial search directory to the current working
|
|
directory - if there is one. */
|
|
|
|
/* First check for a local path pointer stored in the thread control block. This
|
|
is only available in ThreadX Version 4 and above. */
|
|
#ifndef FX_NO_LOCAL_PATH
|
|
if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
|
|
{
|
|
|
|
/* Determine if the local directory is not the root directory. */
|
|
if (((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_directory.fx_dir_entry_name[0])
|
|
{
|
|
|
|
/* Start at the current working directory of the media. */
|
|
search_dir = ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_directory;
|
|
|
|
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
|
|
|
/* Setup pointer to the path. */
|
|
path_ptr = ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_string;
|
|
#endif
|
|
|
|
/* Set the internal pointer to the search directory as well. */
|
|
search_dir_ptr = &search_dir;
|
|
}
|
|
else
|
|
{
|
|
|
|
/* We are searching in the root directory. */
|
|
search_dir_ptr = FX_NULL;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
if (media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0])
|
|
{
|
|
|
|
/* Start at the current working directory of the media. */
|
|
search_dir = media_ptr -> fx_media_default_path.fx_path_directory;
|
|
|
|
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
|
|
|
/* Setup pointer to the path. */
|
|
path_ptr = media_ptr -> fx_media_default_path.fx_path_string;
|
|
#endif
|
|
|
|
/* Set the internal pointer to the search directory as well. */
|
|
search_dir_ptr = &search_dir;
|
|
}
|
|
else
|
|
{
|
|
|
|
/* The current default directory is the root so just set the
|
|
search directory pointer to NULL. */
|
|
search_dir_ptr = FX_NULL;
|
|
}
|
|
}
|
|
|
|
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
|
|
|
/* Determine if there is a previously found directory entry. */
|
|
if (media_ptr -> fx_media_last_found_name[0])
|
|
{
|
|
|
|
UINT match;
|
|
CHAR *temp_ptr, beta;
|
|
|
|
/* Yes, there is a previously found directory in our cache. */
|
|
|
|
/* Initialize the index. */
|
|
v = 0;
|
|
|
|
/* Determine if there is a full path. */
|
|
if ((*name_ptr == '\\') || (*name_ptr == '/'))
|
|
{
|
|
|
|
/* Yes, the full path is in the name buffer. Simply compare with what is in
|
|
the last search buffer. */
|
|
while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (name_ptr[v]))
|
|
{
|
|
|
|
/* Pickup the respective name characters. */
|
|
alpha = name_ptr[v];
|
|
beta = media_ptr -> fx_media_last_found_name[v];
|
|
|
|
/* Ensure directory markers are the same. */
|
|
if (alpha == '\\')
|
|
{
|
|
alpha = '/';
|
|
}
|
|
if (beta == '\\')
|
|
{
|
|
beta = '/';
|
|
}
|
|
|
|
/* Is the name the same? */
|
|
if (alpha != beta)
|
|
{
|
|
|
|
/* Break out of loop! */
|
|
break;
|
|
}
|
|
|
|
/* Move to next character. */
|
|
v++;
|
|
}
|
|
|
|
/* Determine if we have a match. */
|
|
if (name_ptr[v] != media_ptr -> fx_media_last_found_name[v])
|
|
{
|
|
match = FX_FALSE;
|
|
}
|
|
else
|
|
{
|
|
match = FX_TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
/* Default to found. */
|
|
match = FX_TRUE;
|
|
|
|
/* Determine if there is a default path to compare with. */
|
|
if (path_ptr)
|
|
{
|
|
|
|
/* Yes, compare the current path with what is contained in the last
|
|
found buffer. Note that the last found name must have at least one
|
|
path separator as well as room for at least one character for a name. */
|
|
while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (path_ptr[v]))
|
|
{
|
|
|
|
/* Pickup the respective name characters. */
|
|
alpha = media_ptr -> fx_media_last_found_name[v];
|
|
beta = path_ptr[v];
|
|
|
|
/* Ensure directory markers are the same. */
|
|
if (alpha == '\\')
|
|
{
|
|
alpha = '/';
|
|
}
|
|
if (beta == '\\')
|
|
{
|
|
beta = '/';
|
|
}
|
|
|
|
/* Is the name the same? */
|
|
if (alpha != beta)
|
|
{
|
|
|
|
/* Break out of loop! */
|
|
break;
|
|
}
|
|
|
|
/* Move to next character. */
|
|
v++;
|
|
}
|
|
|
|
/* Determine if we don't have a match... The relative path must be exhausted. */
|
|
if (path_ptr[v])
|
|
{
|
|
match = FX_FALSE;
|
|
}
|
|
}
|
|
|
|
/* Determine if we still have a match. */
|
|
if (match)
|
|
{
|
|
|
|
/* Now examine the rest of the last name and the newly supplied
|
|
input name. */
|
|
|
|
/* Determine if a valid directory separator is present. */
|
|
if ((media_ptr -> fx_media_last_found_name[v] != '\\') &&
|
|
(media_ptr -> fx_media_last_found_name[v] != '/'))
|
|
{
|
|
|
|
/* Set match to false - invalid directory path separator. */
|
|
match = FX_FALSE;
|
|
}
|
|
else
|
|
{
|
|
/* Position past the next directory separator in the
|
|
last name string. */
|
|
v++;
|
|
}
|
|
|
|
/* Yes, the full path is in the name buffer. Simply compare with what is in
|
|
the last search buffer. */
|
|
j = 0;
|
|
while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (name_ptr[j]) && (match))
|
|
{
|
|
|
|
/* Pickup the respective name characters. */
|
|
alpha = name_ptr[j];
|
|
beta = media_ptr -> fx_media_last_found_name[v];
|
|
|
|
/* Ensure directory markers are the same. */
|
|
if (alpha == '\\')
|
|
{
|
|
alpha = '/';
|
|
}
|
|
if (beta == '\\')
|
|
{
|
|
beta = '/';
|
|
}
|
|
|
|
/* Is the name the same? */
|
|
if (alpha != beta)
|
|
{
|
|
|
|
/* Break out of loop! */
|
|
break;
|
|
}
|
|
|
|
/* Move to next character. */
|
|
v++;
|
|
j++;
|
|
}
|
|
|
|
/* Avoid accessing fx_media_last_found_name out of bounds. */
|
|
if (v >= 256)
|
|
{
|
|
match = FX_FALSE;
|
|
}
|
|
else if ((match) && (name_ptr[j] != media_ptr -> fx_media_last_found_name[v]))
|
|
{
|
|
|
|
/* We don't have a match. */
|
|
match = FX_FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Now determine if we actually found a match. */
|
|
if (match)
|
|
{
|
|
|
|
/* Save the directory entry name pointer. */
|
|
temp_ptr = entry_ptr -> fx_dir_entry_name;
|
|
|
|
/* Copy the saved directory entry. */
|
|
*entry_ptr = media_ptr -> fx_media_last_found_entry;
|
|
|
|
/* Restore the directory entry name pointer. */
|
|
entry_ptr -> fx_dir_entry_name = temp_ptr;
|
|
|
|
/* Copy the directory name into the destination directory name. */
|
|
for (index = 0; index < FX_MAX_LONG_NAME_LEN; index++)
|
|
{
|
|
|
|
/* Copy character into the destination. */
|
|
temp_ptr[index] = media_ptr -> fx_media_last_found_file_name[index];
|
|
|
|
/* See if we have copied the NULL termination character. */
|
|
if (temp_ptr[index] == (CHAR)FX_NULL)
|
|
{
|
|
|
|
/* Determine if we should break here or at the top of the loop. */
|
|
if (index < (FX_MAX_LONG_NAME_LEN - 1))
|
|
{
|
|
|
|
/* Yes, break out of the loop early. */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Determine if there is a search directory to copy. */
|
|
if ((last_dir_ptr) && (media_ptr -> fx_media_last_found_directory_valid))
|
|
{
|
|
|
|
/* Yes, there was a search directory... and one is requested in this request as well.
|
|
Simply copy it into the destination. */
|
|
|
|
/* First, save the name pointer from the list directory pointer. */
|
|
destination_name_ptr = last_dir_ptr -> fx_dir_entry_name;
|
|
|
|
/* Copy the entire directory entry structure. */
|
|
*last_dir_ptr = media_ptr -> fx_media_last_found_directory;
|
|
|
|
/* Restore the original name buffer pointer. */
|
|
last_dir_ptr -> fx_dir_entry_name = destination_name_ptr;
|
|
|
|
/* Pickup pointer to name to copy. */
|
|
source_name_ptr = media_ptr -> fx_media_last_found_directory.fx_dir_entry_name;
|
|
|
|
/* Loop to copy the name into the last directory name buffer. */
|
|
for (n = 0; n < FX_MAX_LONG_NAME_LEN; n++)
|
|
{
|
|
|
|
/* Copy a character. */
|
|
destination_name_ptr[n] = source_name_ptr[n];
|
|
|
|
/* See if we have copied the NULL termination character. */
|
|
if (source_name_ptr[n] == (CHAR)FX_NULL)
|
|
{
|
|
|
|
/* Determine if we should break here or at the top of the loop. */
|
|
if (n < (FX_MAX_LONG_NAME_LEN - 1))
|
|
{
|
|
|
|
/* Yes, break out of the loop early. */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Return the last name pointer, if required. */
|
|
if (last_name_ptr)
|
|
{
|
|
|
|
/* Just set the last name to initial name string. */
|
|
*last_name_ptr = temp_ptr;
|
|
}
|
|
|
|
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
|
|
|
/* Increment the number of directory search cache hits. */
|
|
media_ptr -> fx_media_directory_search_cache_hits++;
|
|
#endif
|
|
|
|
/* Return success. */
|
|
return(FX_SUCCESS);
|
|
}
|
|
}
|
|
|
|
/* Not a sequential search, invalidate the saved information. */
|
|
media_ptr -> fx_media_last_found_name[0] = FX_NULL;
|
|
|
|
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
|
|
|
/* If trace is enabled, insert this event into the trace buffer. */
|
|
FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_DIR_CACHE_MISS, media_ptr, media_ptr -> fx_media_directory_searches - media_ptr -> fx_media_directory_search_cache_hits, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
|
|
#else
|
|
|
|
/* If trace is enabled, insert this event into the trace buffer. */
|
|
FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_DIR_CACHE_MISS, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
|
|
#endif
|
|
#endif
|
|
|
|
/* Loop to traverse the directory paths to find the specified file. */
|
|
do
|
|
{
|
|
|
|
/* Remember the last name pointer, if required. */
|
|
if (last_name_ptr)
|
|
{
|
|
|
|
/* Just set the last name to initial name string. */
|
|
*last_name_ptr = name_ptr;
|
|
}
|
|
|
|
/* Extract file name. */
|
|
name_ptr = _fx_directory_name_extract(name_ptr, name);
|
|
|
|
/* Calculate the directory size. */
|
|
if (search_dir_ptr)
|
|
{
|
|
|
|
/* Ensure that the search directory's last search cluster is cleared. */
|
|
search_dir_ptr -> fx_dir_entry_last_search_cluster = 0;
|
|
|
|
/* Calculate the directory size by counting the allocated
|
|
clusters for it. */
|
|
i = 0;
|
|
cluster = search_dir_ptr -> fx_dir_entry_cluster;
|
|
while (cluster < media_ptr -> fx_media_fat_reserved)
|
|
{
|
|
|
|
/* Increment the cluster count. */
|
|
i++;
|
|
|
|
/* Read the next FAT entry. */
|
|
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
|
|
|
|
/* Check the return status. */
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
|
|
/* Return the bad status. */
|
|
return(status);
|
|
}
|
|
|
|
/* Check for error situation. */
|
|
if ((cluster < FX_FAT_ENTRY_START) || (cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
|
|
{
|
|
|
|
/* Return the bad status. */
|
|
return(FX_FAT_READ_ERROR);
|
|
}
|
|
|
|
cluster = next_cluster;
|
|
}
|
|
|
|
/* Now we can calculate the directory size. */
|
|
directory_size = (((ULONG64) media_ptr -> fx_media_bytes_per_sector) *
|
|
((ULONG64) media_ptr -> fx_media_sectors_per_cluster) * i)
|
|
/ (ULONG64) FX_DIR_ENTRY_SIZE;
|
|
|
|
/* Also save this in the directory entry so we don't have to
|
|
calculate it later. */
|
|
search_dir_ptr -> fx_dir_entry_file_size = directory_size;
|
|
|
|
/* If required, copy the last search directory entry into the
|
|
destination. */
|
|
if (last_dir_ptr)
|
|
{
|
|
|
|
/* Copy the last search directory into the destination. */
|
|
|
|
/* First, save the name pointer from the list directory pointer. */
|
|
destination_name_ptr = last_dir_ptr -> fx_dir_entry_name;
|
|
|
|
/* Copy the entire directory entry structure. */
|
|
*last_dir_ptr = *search_dir_ptr;
|
|
|
|
/* Restore the original name buffer pointer. */
|
|
last_dir_ptr -> fx_dir_entry_name = destination_name_ptr;
|
|
|
|
/* Pickup pointer to name to copy. */
|
|
source_name_ptr = search_dir_ptr -> fx_dir_entry_name;
|
|
|
|
/* Loop to copy the name into the last directory name buffer. */
|
|
for (n = 0; n < FX_MAX_LONG_NAME_LEN; n++)
|
|
{
|
|
|
|
/* Copy a character. */
|
|
destination_name_ptr[n] = source_name_ptr[n];
|
|
|
|
/* See if we have copied the NULL termination character. */
|
|
if (source_name_ptr[n] == (CHAR) FX_NULL)
|
|
{
|
|
|
|
/* Determine if we should break here or at the top of the loop. */
|
|
if (n < (FX_MAX_LONG_NAME_LEN - 1))
|
|
{
|
|
|
|
/* Yes, break out of the loop early. */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
/* Directory size is the number of entries in the root directory. */
|
|
directory_size = (ULONG)media_ptr -> fx_media_root_directory_entries;
|
|
}
|
|
|
|
/* Loop through entries in the directory. Yes, this is a
|
|
linear search! */
|
|
i = 0;
|
|
found = FX_FALSE;
|
|
|
|
|
|
do
|
|
{
|
|
|
|
/* Read an entry from the directory. */
|
|
status = _fx_directory_entry_read(media_ptr, search_dir_ptr, &i, entry_ptr);
|
|
|
|
i++;
|
|
|
|
/* Check for error status. */
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
return(status);
|
|
}
|
|
|
|
/* Determine if this is the last directory entry. */
|
|
if ((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_DONE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
/* Determine if the entry is a volume label entry */
|
|
if ((entry_ptr -> fx_dir_entry_attributes & FX_VOLUME))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
/* Determine if this is an empty entry. */
|
|
if (((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_FREE) && (entry_ptr -> fx_dir_entry_short_name[0] == 0))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
/* Compare the input name and extension with the directory
|
|
entry. */
|
|
work_ptr = &name[0];
|
|
dir_name_ptr = &(entry_ptr -> fx_dir_entry_name[0]);
|
|
|
|
/* Loop to compare names. */
|
|
do
|
|
{
|
|
|
|
/* Pickup character of directory name. */
|
|
alpha = *dir_name_ptr;
|
|
|
|
/* Pickup character of name. */
|
|
name_alpha = *work_ptr;
|
|
|
|
/* Determine if its case needs to be changed. */
|
|
if ((alpha >= 'a') && (alpha <= 'z'))
|
|
{
|
|
|
|
/* Yes, make upper case. */
|
|
alpha = (CHAR)((INT)alpha - 0x20);
|
|
}
|
|
|
|
/* Determine if its case needs to be changed. */
|
|
if ((name_alpha >= 'a') && (name_alpha <= 'z'))
|
|
{
|
|
|
|
/* Yes, make upper case. */
|
|
name_alpha = (CHAR)((INT)name_alpha - 0x20);
|
|
}
|
|
|
|
/* Compare name with directory name. */
|
|
if (alpha != name_alpha)
|
|
{
|
|
|
|
/* The names don't match, get out of the loop. */
|
|
break;
|
|
}
|
|
|
|
/* Otherwise, increment the name pointers. */
|
|
work_ptr++;
|
|
dir_name_ptr++;
|
|
} while (*dir_name_ptr);
|
|
|
|
/* Determine if the requested name has been found. If so,
|
|
return success to the caller. */
|
|
if ((*dir_name_ptr == 0) && (*work_ptr == *dir_name_ptr))
|
|
{
|
|
|
|
/* Yes, the name was located. All pertinent directory
|
|
information is in the directory entry field. */
|
|
found = FX_TRUE;
|
|
}
|
|
/* Determine if there is a short name to check. */
|
|
else if (entry_ptr -> fx_dir_entry_short_name[0] != 0)
|
|
{
|
|
|
|
/* Yes, check for the short part of the name. */
|
|
|
|
/* Compare the input name and extension with the directory entry. */
|
|
work_ptr = &name[0];
|
|
dir_name_ptr = &(entry_ptr -> fx_dir_entry_short_name[0]);
|
|
|
|
/* Loop to compare names. */
|
|
do
|
|
{
|
|
|
|
/* Pickup character of directory name. */
|
|
alpha = *dir_name_ptr;
|
|
|
|
/* Pickup character of name. */
|
|
name_alpha = *work_ptr;
|
|
|
|
/* Determine if its case needs to be changed. */
|
|
if ((name_alpha >= 'a') && (name_alpha <= 'z'))
|
|
{
|
|
|
|
/* Yes, make upper case. */
|
|
name_alpha = (CHAR)((INT)name_alpha - 0x20);
|
|
}
|
|
|
|
/* Compare name with directory name. */
|
|
if (alpha != name_alpha)
|
|
{
|
|
|
|
/* The names don't match, get out of the loop. */
|
|
break;
|
|
}
|
|
|
|
/* Otherwise, move the name pointers and increment the
|
|
count. */
|
|
work_ptr++;
|
|
dir_name_ptr++;
|
|
} while (*dir_name_ptr);
|
|
|
|
/* Determine if the names match. */
|
|
if ((*dir_name_ptr == 0) && (*work_ptr == *dir_name_ptr))
|
|
{
|
|
|
|
/* Yes, the name was located. All pertinent directory
|
|
information is in the directory entry field. */
|
|
found = FX_TRUE;
|
|
}
|
|
}
|
|
} while ((i < directory_size) && (!found));
|
|
|
|
/* Now determine if we have a match. */
|
|
if (!found)
|
|
{
|
|
|
|
/* Return a "not found" status to the caller. */
|
|
return(FX_NOT_FOUND);
|
|
}
|
|
|
|
/* Determine if the found entry is indeed a sub-directory. */
|
|
if (entry_ptr -> fx_dir_entry_attributes & FX_DIRECTORY)
|
|
{
|
|
|
|
/* Move the directory search pointer to this entry. */
|
|
search_dir = *entry_ptr;
|
|
search_dir_ptr = &search_dir;
|
|
|
|
/* Ensure that the search directory's last search cluster is cleared. */
|
|
search_dir_ptr -> fx_dir_entry_last_search_cluster = 0;
|
|
|
|
/* Now determine if the new search directory is the root
|
|
directory. */
|
|
if (!search_dir_ptr -> fx_dir_entry_cluster)
|
|
{
|
|
|
|
/* This is a backward link to the root directory. Make
|
|
sure this is indicated in the search directory
|
|
information. */
|
|
search_dir_ptr -> fx_dir_entry_name[0] = 0;
|
|
|
|
/* Determine if we need to remember this in the last
|
|
directory searched return area. */
|
|
if (last_dir_ptr)
|
|
{
|
|
|
|
/* Yes, return this value to the caller. */
|
|
|
|
/* First, save the name pointer from the list directory pointer. */
|
|
destination_name_ptr = last_dir_ptr -> fx_dir_entry_name;
|
|
|
|
/* Copy the entire directory entry structure. */
|
|
*last_dir_ptr = *search_dir_ptr;
|
|
|
|
/* Restore the original name buffer pointer. */
|
|
last_dir_ptr -> fx_dir_entry_name = destination_name_ptr;
|
|
|
|
/* Pickup pointer to name to copy. */
|
|
source_name_ptr = search_dir_ptr -> fx_dir_entry_name;
|
|
|
|
/* Loop to copy the name into the last directory name buffer. */
|
|
for (n = 0; n < FX_MAX_LONG_NAME_LEN; n++)
|
|
{
|
|
|
|
/* Copy a character. */
|
|
destination_name_ptr[n] = source_name_ptr[n];
|
|
}
|
|
}
|
|
|
|
/* Set the search directory pointer to NULL to indicate
|
|
we are at the root directory. */
|
|
search_dir_ptr = FX_NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
/* This is not a directory, we better return not found
|
|
since we can't continue the search. */
|
|
if (name_ptr)
|
|
{
|
|
|
|
/* Return not-found status to caller. */
|
|
return(FX_NOT_FOUND);
|
|
}
|
|
}
|
|
} while (name_ptr);
|
|
|
|
/* If you reach this point, the directory is found absolutely, since !found will return directly in the loop above. */
|
|
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
|
|
|
|
|
/* At this point, cache the found information. If a subsequent search for the same name is done,
|
|
it will return immediately. */
|
|
|
|
/* Set the index of the saved name string. */
|
|
v= 0;
|
|
|
|
/* First, build the full path and name. */
|
|
if ((*original_name != '\\') && (*original_name != '/') && (path_ptr))
|
|
{
|
|
|
|
/* Copy the path into the destination. */
|
|
while ((v< (FX_MAX_LAST_NAME_LEN - 1)) && (path_ptr[v]))
|
|
{
|
|
|
|
/* Copy one character. */
|
|
media_ptr -> fx_media_last_found_name[v] = path_ptr[v];
|
|
|
|
/* Move to next character. */
|
|
v++;
|
|
}
|
|
}
|
|
|
|
/* Now see if there is no directory path symbol in the name itself. */
|
|
if ((*original_name != '\\') && (*original_name != '/'))
|
|
{
|
|
|
|
/* If there is room, place a directory separator character. */
|
|
if (v < (FX_MAX_LAST_NAME_LEN - 1))
|
|
{
|
|
media_ptr -> fx_media_last_found_name[v++] = '/';
|
|
}
|
|
}
|
|
|
|
/* Now append the name to the path. */
|
|
j = 0;
|
|
while ((v < FX_MAX_LAST_NAME_LEN) && (original_name[j]))
|
|
{
|
|
|
|
/* Copy one character. */
|
|
media_ptr -> fx_media_last_found_name[v] = original_name[j];
|
|
|
|
/* Move to next character. */
|
|
v++;
|
|
j++;
|
|
}
|
|
|
|
/* Null terminate the last name string. */
|
|
if (v< FX_MAX_LAST_NAME_LEN)
|
|
{
|
|
|
|
/* Null terminate. */
|
|
media_ptr -> fx_media_last_found_name[v] = FX_NULL;
|
|
}
|
|
else
|
|
{
|
|
|
|
/* The string is too big, NULL the string so it won't be used in searching. */
|
|
media_ptr -> fx_media_last_found_name[0] = FX_NULL;
|
|
}
|
|
|
|
/* Determine if there is a search pointer. */
|
|
if (search_dir_ptr)
|
|
{
|
|
|
|
/* Yes, there is a search directory pointer so save it! */
|
|
media_ptr -> fx_media_last_found_directory = *search_dir_ptr;
|
|
|
|
/* Indicate the search directory is valid. */
|
|
media_ptr -> fx_media_last_found_directory_valid = FX_TRUE;
|
|
}
|
|
else
|
|
{
|
|
|
|
/* Indicate the search directory is not valid. */
|
|
media_ptr -> fx_media_last_found_directory_valid = FX_FALSE;
|
|
}
|
|
|
|
/* Copy the directory entry. */
|
|
media_ptr -> fx_media_last_found_entry = *entry_ptr;
|
|
|
|
/* Setup the directory entry for the last found internal file name. */
|
|
media_ptr -> fx_media_last_found_entry.fx_dir_entry_name = media_ptr -> fx_media_last_found_file_name;
|
|
|
|
/* Copy the actual directory name into the cached directory name. */
|
|
for (index = 0; index < FX_MAX_LONG_NAME_LEN; index++)
|
|
{
|
|
|
|
/* Copy character into the cached directory name. */
|
|
media_ptr -> fx_media_last_found_file_name[index] = entry_ptr -> fx_dir_entry_name[index];
|
|
|
|
/* See if we have copied the NULL termination character. */
|
|
if (entry_ptr -> fx_dir_entry_name[index] == (CHAR)FX_NULL)
|
|
{
|
|
|
|
/* Check to see if we use the break to get out of the loop. */
|
|
if (index < (FX_MAX_LONG_NAME_LEN - 1))
|
|
{
|
|
|
|
/* Yes, not at the end of the string, break. */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return(FX_SUCCESS);
|
|
}
|
|
|