FX_FO.C
上传用户:super_houu
上传日期:2008-09-21
资源大小:4099k
文件大小:22k
- /**************************************************************************/
- /* */
- /* Copyright (c) 1996-2002 by Express Logic Inc. */
- /* */
- /* This software is copyrighted by and is the sole property of Express */
- /* Logic, Inc. All rights, title, ownership, or other interests */
- /* in the software remain the property of Express Logic, Inc. This */
- /* software may only be used in accordance with the corresponding */
- /* license agreement. Any unauthorized use, duplication, transmission, */
- /* distribution, or disclosure of this software is expressly forbidden. */
- /* */
- /* This Copyright notice may not be removed or modified without prior */
- /* written consent of Express Logic, Inc. */
- /* */
- /* Express Logic, Inc. reserves the right to modify this software */
- /* without notice. */
- /* */
- /* Express Logic, Inc. info@expresslogic.com */
- /* 11423 West Bernardo Court http://www.expresslogic.com */
- /* San Diego, CA 92127 */
- /* */
- /**************************************************************************/
- /**************************************************************************/
- /**************************************************************************/
- /** */
- /** FileX Component */
- /** */
- /** File (FIL) */
- /** */
- /**************************************************************************/
- /**************************************************************************/
- #include "Config.h" // Global Configuration - do not remove!
- #ifdef ENABLE_FILEX
- #ifdef _DEBUG
- #undef IFTRACE
- #define IFTRACE if (gTraceFileSys)
- #include "DebugDbgMain.h"
- #endif //_DEBUG
- #define FX_SOURCE_CODE
- /* Include necessary system files. */
- #include "PlaycoreFileSysFileXfx_api.h"
- #include "PlaycoreFileSysFileXfx_sys.h"
- #include "PlaycoreFileSysFileXfx_dir.h"
- #include "PlaycoreFileSysFileXfx_fil.h"
- #include "PlaycoreFileSysFileXfx_uti.h"
- /**************************************************************************/
- /* */
- /* FUNCTION RELEASE */
- /* */
- /* _fx_file_open PORTABLE C */
- /* 3.0 */
- /* AUTHOR */
- /* */
- /* William E. Lamie, Express Logic, Inc. */
- /* */
- /* DESCRIPTION */
- /* */
- /* This function first attempts to find the specified file. If found, */
- /* the open request is validated and the file is opened. During the */
- /* opening process, all of the FAT entries for this file are examined */
- /* for their integrity. */
- /* */
- /* INPUT */
- /* */
- /* media_ptr Media control block pointer */
- /* file_ptr File control block pointer */
- /* name_ptr Name pointer (8 chars + ext) */
- /* open_type Type of open requested */
- /* */
- /* OUTPUT */
- /* */
- /* return status */
- /* */
- /* CALLS */
- /* */
- /* _fx_directory_search Search for the file name in */
- /* the directory structure */
- /* _fx_utility_FAT_entry_read Read a FAT entry */
- /* */
- /* CALLED BY */
- /* */
- /* Application Code */
- /* */
- /* RELEASE HISTORY */
- /* */
- /* DATE NAME DESCRIPTION */
- /* */
- /* 01-01-1999 William E. Lamie Initial Version 1.0 */
- /* 04-19-1999 William E. Lamie Added logic to setup a file */
- /* opened for writing whose */
- /* size is evenly divisible by */
- /* the media's cluster size, */
- /* resulting in version 1.0a. */
- /* 03-01-2000 William E. Lamie Modified comment(s), and */
- /* added casting to remove */
- /* compiler warning message, */
- /* resulting in version 1.0b. */
- /* 01-28-2001 William E. Lamie Modified comment(s) and added */
- /* logic to allow opening of */
- /* initially null open files, */
- /* resulting in version 2.0. */
- /* 03-01-2002 Mohammad N. Minhaz Modified comment(s), */
- /* changed to 32 bit variables,*/
- /* fixed possible infinite loop*/
- /* caused by a corrupted FAT, */
- /* determined consecutive */
- /* clusters, and added write */
- /* protect logic, resulting in */
- /* version 3.0. */
- /* */
- /**************************************************************************/
- UINT _fx_file_open(FX_MEDIA *media_ptr, FX_FILE *file_ptr, CHAR *file_name, UINT open_type)
- {
- UINT status, leading_consecutive;
- ULONG cluster;
- ULONG contents;
- ULONG open_count;
- FX_FILE *tail_ptr;
- FX_FILE *search_ptr;
- ULONG bytes_per_cluster;
- ULONG last_cluster;
- ULONG cluster_count;
- ULONG bytes_available;
- ULONG bytes_remaining;
- ULONG fat_reserved, fat_last;
- /* Check the media to make sure it is open. */
- if (media_ptr -> fx_media_id != FX_MEDIA_ID)
- {
- /* Return the media not opened error. */
- return(FX_MEDIA_NOT_OPEN);
- }
- /* Determine the type of FAT and setup variables accordingly. */
- if (media_ptr -> fx_media_32_bit_FAT) fat_reserved = FX_RESERVED_1_32;
- else fat_reserved = FX_RESERVED_1;
- if (media_ptr -> fx_media_32_bit_FAT) fat_last = FX_LAST_CLUSTER_1_32;
- else fat_last = FX_LAST_CLUSTER_1;
- /* Protect against other threads accessing the media. */
- FX_PROTECT
- /* Search the system for the supplied file name. */
- status = _fx_directory_search(media_ptr, file_name, &(file_ptr -> fx_file_dir_entry), FX_NULL, FX_NULL);
- /* Determine if the search was successful. */
- if (status != FX_SUCCESS)
- {
- /* Release media protection. */
- FX_UNPROTECT
- /* Return the error code. */
- return(status);
- }
- /* Check to make sure the found entry is a file. */
- if (file_ptr -> fx_file_dir_entry.fx_dir_entry_attributes & (UCHAR) (FX_DIRECTORY | FX_VOLUME))
- {
- /* Release media protection. */
- FX_UNPROTECT
- /* Return the not a file error code. */
- return(FX_NOT_A_FILE);
- }
- /* Check to make sure the access is okay. */
- if (open_type == FX_OPEN_FOR_READ)
- {
- #if 0 //don't maintain any file list.
- /* Check the list of open files for others open for writing. */
- open_count = media_ptr -> fx_media_opened_file_count;
- search_ptr = media_ptr -> fx_media_opened_file_list;
- while(open_count)
- {
- /* Look at each opened file to see if the same file is opened
- for writing. */
- if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector ==
- file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector) &&
- (search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset ==
- file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset) &&
- (search_ptr -> fx_file_open_mode))
- {
- /* Release media protection. */
- FX_UNPROTECT
- /* The file has been opened for writing by a previous call. */
- return(FX_ACCESS_ERROR);
- }
- /* Adjust the pointer and decrement the search count. */
- search_ptr = search_ptr -> fx_file_opened_next;
- open_count--;
- }
- #endif
- }
- #if 0 //don't maintain any file list.
- else
- {
- /* A open for write request is present, check the file attributes
- and the list of open files for any other open instance of
- this file. */
- if (media_ptr -> fx_media_driver_write_protect)
- {
- /* Release media protection. */
- FX_UNPROTECT
- /* Return write protect error. */
- return(FX_WRITE_PROTECT);
- }
- if (file_ptr -> fx_file_dir_entry.fx_dir_entry_attributes & (UCHAR) (FX_READ_ONLY))
- {
- /* Release media protection. */
- FX_UNPROTECT
- /* Return the not a file error code. */
- return(FX_ACCESS_ERROR);
- }
- /* Also search the opened files to see if this file is currently
- opened. */
- open_count = media_ptr -> fx_media_opened_file_count;
- search_ptr = media_ptr -> fx_media_opened_file_list;
- while(open_count)
- {
- /* Look at each opened file to see if the same file is opened
- for writing. */
- if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector ==
- file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector) &&
- (search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset ==
- file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset))
- {
- /* Release media protection. */
- FX_UNPROTECT
- /* The file is currently open. */
- return(FX_ACCESS_ERROR);
- }
- /* Adjust the pointer and decrement the search count. */
- search_ptr = search_ptr -> fx_file_opened_next;
- open_count--;
- }
- }
- #endif
- /* At this point, we are ready to walk list of clusters to setup the
- initial condition of this file as well as to verify its integrity. */
- cluster = file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster;
- bytes_remaining = file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size;
- bytes_per_cluster = ((ULONG) media_ptr -> fx_media_bytes_per_sector) *
- ((ULONG) media_ptr -> fx_media_sectors_per_cluster);
- file_ptr -> fx_file_current_physical_cluster = 0;
- last_cluster = 0;
- cluster_count = 0;
- leading_consecutive = 1;
- file_ptr -> fx_file_consecutive_cluster = 1;
- /* Follow the link of FAT entries. */
- while ((cluster >= FX_FAT_ENTRY_START) && (cluster < fat_reserved))
- {
- /* Increment the number of clusters. */
- cluster_count++;
- /* Read the current cluster entry from the FAT. */
- status = _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
- /* Check the return value. */
- if (status != FX_SUCCESS)
- {
- /* Release media protection. */
- FX_UNPROTECT
- /* Return the error status. */
- return(status);
- }
- if ((cluster == contents) || (cluster_count > media_ptr -> fx_media_total_clusters))
- {
- /* Release media protection. */
- FX_UNPROTECT
- /* Return the bad status. */
- return(FX_FAT_READ_ERROR);
- }
- /* Check if present and next clusters are consecutive */
- if (cluster + 1 == contents)
- {
- /* Save the number of leading consecutive clusters */
- if (leading_consecutive)
- file_ptr -> fx_file_consecutive_cluster ++;
- }
- else
- leading_consecutive = 0;
- /* Save the last valid cluster. */
- last_cluster = cluster;
- /* Setup for the next cluster. */
- cluster = contents;
- /* Determine if this is the last written cluster. We need to remember this
- for open for writing. */
- if (bytes_remaining > bytes_per_cluster)
- {
- /* Still more written clusters, just decrement the counter. */
- bytes_remaining = bytes_remaining - bytes_per_cluster;
- }
- else if (!file_ptr -> fx_file_current_physical_cluster)
- {
- /* Remember this cluster number. */
- file_ptr -> fx_file_current_physical_cluster = last_cluster;
- /* Remember the relative cluster. */
- file_ptr -> fx_file_current_relative_cluster = cluster_count-1;
- /* If the remaining bytes exactly fits the cluster size, check for
- a possible adjustment to the next cluster. */
- if ((bytes_remaining == bytes_per_cluster) &&
- (cluster >= FX_FAT_ENTRY_START) && (cluster < fat_reserved))
- {
- /* We need to position to next allocated cluster. */
- file_ptr -> fx_file_current_physical_cluster = cluster;
- file_ptr -> fx_file_current_relative_cluster++;
- /* Clear the remaining bytes. */
- bytes_remaining = 0;
- }
- }
- }
- /* Determine if the number of clusters is large enough to support the
- specified file size. */
- bytes_available = ((ULONG) media_ptr -> fx_media_bytes_per_sector) *
- ((ULONG) media_ptr -> fx_media_sectors_per_cluster) *
- ((ULONG) cluster_count);
- if ((bytes_available < file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size) ||
- ((cluster_count) && (contents < fat_last)))
- {
- /* Release media protection. */
- FX_UNPROTECT
- /* Return a corrupt file error status. */
- return(FX_FILE_CORRUPT);
- }
- /* The file is okay, populate the file control block and complete the
- file open process. */
- file_ptr -> fx_file_id = FX_FILE_ID;
- file_ptr -> fx_file_name = file_name;
- file_ptr -> fx_file_media_ptr = media_ptr;
- file_ptr -> fx_file_open_mode = (UCHAR) open_type;
- file_ptr -> fx_file_modified = FX_FALSE;
- file_ptr -> fx_file_total_clusters = cluster_count;
- file_ptr -> fx_file_first_physical_cluster = file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster;
- file_ptr -> fx_file_last_physical_cluster = last_cluster;
- file_ptr -> fx_file_current_file_size = file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size;
- file_ptr -> fx_file_current_available_size = bytes_available;
- /* Set the current settings based on how the file was opened. */
- if (open_type == FX_OPEN_FOR_READ)
- {
- /* Position the pointers to the beginning of the file. */
- file_ptr -> fx_file_current_physical_cluster = file_ptr -> fx_file_first_physical_cluster;
- file_ptr -> fx_file_current_relative_cluster = 0;
- file_ptr -> fx_file_current_logical_sector = ((ULONG) media_ptr -> fx_media_data_sector_start) +
- (((ULONG) (file_ptr -> fx_file_first_physical_cluster - FX_FAT_ENTRY_START)) *
- ((ULONG) media_ptr -> fx_media_sectors_per_cluster));
- file_ptr -> fx_file_current_relative_sector = 0;
- file_ptr -> fx_file_current_logical_offset = 0;
- file_ptr -> fx_file_current_file_offset = 0;
- }
- else
- {
- /* Open for writing - position the pointers to the end of the file. */
- /* Determine if the remaining bytes fit exactly into the cluster size. */
- if (bytes_remaining == bytes_per_cluster)
- {
- /* Position to the end of the cluster. */
- file_ptr -> fx_file_current_logical_sector = ((ULONG) media_ptr -> fx_media_data_sector_start) +
- (((ULONG) file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
- ((ULONG) media_ptr -> fx_media_sectors_per_cluster)) +
- ((bytes_remaining-1) / (ULONG) media_ptr -> fx_media_bytes_per_sector);
- file_ptr -> fx_file_current_relative_sector = (UINT) (((bytes_remaining-1) / (ULONG) media_ptr -> fx_media_bytes_per_sector));
- file_ptr -> fx_file_current_file_offset = file_ptr -> fx_file_current_file_size;
- file_ptr -> fx_file_current_logical_offset = media_ptr -> fx_media_bytes_per_sector;
- }
- else
- {
- /* Position file parameters at end of last cluster allocation. */
- file_ptr -> fx_file_current_logical_sector = ((ULONG) media_ptr -> fx_media_data_sector_start) +
- (((ULONG) file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
- ((ULONG) media_ptr -> fx_media_sectors_per_cluster)) +
- (bytes_remaining / (ULONG) media_ptr -> fx_media_bytes_per_sector);
- file_ptr -> fx_file_current_relative_sector = (UINT) ((bytes_remaining / (ULONG) media_ptr -> fx_media_bytes_per_sector));
- file_ptr -> fx_file_current_file_offset = file_ptr -> fx_file_current_file_size;
- file_ptr -> fx_file_current_logical_offset = bytes_remaining % ((ULONG) media_ptr -> fx_media_bytes_per_sector);
- }
- }
- #if 0 //don't maintain any file list.
- /* Place newly opened file on the list of open files for
- this media. First, check for an empty list. */
- if (media_ptr -> fx_media_opened_file_list)
- {
- /* Pickup tail pointer. */
- tail_ptr = (media_ptr -> fx_media_opened_file_list) -> fx_file_opened_previous;
- /* Place the new file in the list. */
- (media_ptr -> fx_media_opened_file_list) -> fx_file_opened_previous = file_ptr;
- tail_ptr -> fx_file_opened_next = file_ptr;
- /* Setup this file's opened links. */
- file_ptr -> fx_file_opened_previous = tail_ptr;
- file_ptr -> fx_file_opened_next = media_ptr -> fx_media_opened_file_list;
- }
- else
- {
- /* The opened media list is empty. Add the media to empty list. */
- media_ptr -> fx_media_opened_file_list = file_ptr;
- file_ptr -> fx_file_opened_next = file_ptr;
- file_ptr -> fx_file_opened_previous = file_ptr;
- }
- /* Increment the opened file counter. */
- media_ptr -> fx_media_opened_file_count++;
- #endif
- /* Release media protection. */
- FX_UNPROTECT
- /* Open is complete, return successful status. */
- return(FX_SUCCESS);
- }
- #endif