_mfs_error MFS_Get_current_dir ( MQX_FILE_PTR mfs_fd_ptr, /*[IN] pointer to the file struct returned by fopen("MFS...:",..); */ char_ptr buffer_address /*[IN/OUT] address of the buffer where the pathname is to be written */ ) { MFS_DRIVE_STRUCT_PTR drive_ptr; _mfs_error error_code; if ( buffer_address == NULL ) { return MFS_INVALID_PARAMETER; } error_code = MFS_lock_dos_disk( mfs_fd_ptr, &drive_ptr ); if ( error_code != MFS_NO_ERROR ) { return error_code; } strcpy(buffer_address, drive_ptr->CURRENT_DIR); MFS_unlock(drive_ptr,FALSE); return(error_code); }
uint_64 MFS_Get_disk_free_space ( MQX_FILE_PTR mfs_fd_ptr ) { MFS_DRIVE_STRUCT_PTR drive_ptr; uint_32 clusters_free; uint_32 error_code; uint_64 bytes_free; if ( MFS_lock_dos_disk( mfs_fd_ptr, &drive_ptr) != MFS_NO_ERROR ) { return 0; } clusters_free = MFS_Get_disk_free_space_internal(drive_ptr,&error_code); if (error_code == MFS_NO_ERROR) { bytes_free = clusters_free << drive_ptr->CLUSTER_POWER_BYTES; } else { bytes_free = 0; } MFS_unlock(drive_ptr,FALSE); return bytes_free; }
_mfs_error MFS_Set_file_attributes ( MQX_FILE_PTR mfs_fd_ptr, char _PTR_ pathname, /*[IN] pathname of the specific file */ uchar_ptr attribute_ptr /*[IN] attribute of file */ ) { MFS_DRIVE_STRUCT_PTR drive_ptr; MFS_DIR_ENTRY_PTR dir_entry_ptr; _mfs_error error_code; uint_32 dir_cluster, dir_index; uchar at, attrib; uint_32 prev_cluster= CLUSTER_INVALID; if ( (pathname == NULL) || (*pathname == '\0') ) { return MFS_INVALID_PARAMETER; } #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (mfs_fd_ptr, NULL)) { return MFS_DISK_IS_WRITE_PROTECTED; } #endif error_code = MFS_lock_dos_disk( mfs_fd_ptr, &drive_ptr ); if ( error_code != MFS_NO_ERROR ) { return error_code; } attrib = *attribute_ptr; attrib &= MFS_ATTR_ARCHIVE | MFS_ATTR_READ_ONLY | MFS_ATTR_HIDDEN_FILE | MFS_ATTR_SYSTEM_FILE; dir_entry_ptr = MFS_Find_entry_on_disk(drive_ptr, pathname, &error_code, &dir_cluster, &dir_index, &prev_cluster); if ( error_code == MFS_NO_ERROR ) { at = dtohc(dir_entry_ptr->ATTRIBUTE); if ( at != *attribute_ptr ) { /* ** The volume-label and the directory-name are mutually exclusive. ** The volume-label cannot act as a directory-name. Check whether ** you are trying to set the attributes to a volume. */ if ( ! ((at & MFS_ATTR_VOLUME_NAME) || (*attribute_ptr & MFS_ATTR_VOLUME_NAME)) ) { htodc(dir_entry_ptr->ATTRIBUTE, *attribute_ptr); drive_ptr->DIR_SECTOR_DIRTY = TRUE; } else { error_code = MFS_ACCESS_DENIED; } } } MFS_unlock(drive_ptr,TRUE); return(error_code); }
_mfs_error MFS_Get_current_dir ( MFS_DRIVE_STRUCT_PTR drive_ptr, char *buffer_address /*[IN/OUT] address of the buffer where the pathname is to be written */ ) { _mfs_error error_code; if ( buffer_address == NULL ) { return MFS_INVALID_PARAMETER; } error_code = MFS_lock_dos_disk( drive_ptr ); if ( error_code != MFS_NO_ERROR ) { return error_code; } strcpy(buffer_address, drive_ptr->CURRENT_DIR); MFS_unlock(drive_ptr,FALSE); return(error_code); }
_mfs_error MFS_Check_dir_exist ( MFS_DRIVE_STRUCT_PTR drive_ptr, char *pathname /*[IN] pathname of the directory to become the current dir */ ) { uint32_t dir_cluster; _mfs_error error_code; char *directory; // for empty string return error if ( (pathname == NULL) || (*pathname == '\0') ) { return MFS_INVALID_PARAMETER; } // allocate memory for directory error_code = MFS_alloc_path(&directory); if ( error_code != MFS_NO_ERROR ) { return( error_code ); } error_code = MFS_lock_dos_disk( drive_ptr ); if ( error_code != MFS_NO_ERROR ) { MFS_free_path(directory); return error_code; } dir_cluster = ROOT_CLUSTER(drive_ptr); dir_cluster = MFS_Find_directory(drive_ptr, pathname, dir_cluster); if ( dir_cluster == CLUSTER_INVALID ) { error_code = MFS_PATH_NOT_FOUND; } MFS_free_path(directory); MFS_unlock(drive_ptr,FALSE); return(error_code); }
_mfs_error MFS_Check_dir_exist ( MQX_FILE_PTR mfs_fd_ptr, /*[IN] pointer to the file struct returned by fopen("MFS...:",..); */ char_ptr pathname /*[IN] pathname of the directory to become the current dir */ ) { MFS_DRIVE_STRUCT_PTR drive_ptr; uint_32 dir_cluster; _mfs_error error_code; char_ptr directory; // for empty string return error if ( (pathname == NULL) || (*pathname == '\0') ) { return MFS_INVALID_PARAMETER; } // allocate memory for directory error_code = MFS_alloc_path(&directory); if ( error_code != MFS_NO_ERROR ) { return( error_code ); } error_code = MFS_lock_dos_disk( mfs_fd_ptr, &drive_ptr ); if ( error_code != MFS_NO_ERROR ) { MFS_free_path(directory); return error_code; } dir_cluster = ROOT_CLUSTER(drive_ptr); dir_cluster = MFS_Find_directory(drive_ptr, pathname, dir_cluster); if ( dir_cluster == CLUSTER_INVALID ) { error_code = MFS_PATH_NOT_FOUND; } MFS_free_path(directory); MFS_unlock(drive_ptr,FALSE); return(error_code); }
_mfs_error MFS_Find_next_file ( MQX_FILE_PTR mfs_fd_ptr, /*[IN] pointer to the file struct returned by fopen("MFS...:",..); */ MFS_SEARCH_DATA_PTR transfer_ptr /* [IN/OUT] address of search data block indicating the current criteria and the results of ** the last search results of this search are placed in this data block */ ) { MFS_DRIVE_STRUCT_PTR drive_ptr; _mfs_error error_code; error_code = MFS_lock_dos_disk( mfs_fd_ptr, &drive_ptr ); if ( error_code == MFS_NO_ERROR ) { error_code = MFS_Find_next_slave(drive_ptr, transfer_ptr); MFS_unlock(drive_ptr,FALSE); } return(error_code); }
_mfs_error MFS_Find_next_file ( MFS_DRIVE_STRUCT_PTR drive_ptr, MFS_SEARCH_DATA_PTR transfer_ptr /* [IN/OUT] address of search data block indicating the current criteria and the results of ** the last search results of this search are placed in this data block */ ) { _mfs_error error_code; error_code = MFS_lock_dos_disk( drive_ptr ); if ( error_code == MFS_NO_ERROR ) { error_code = MFS_Find_next_slave(drive_ptr, transfer_ptr); MFS_unlock(drive_ptr,FALSE); } return(error_code); }
uint_32 MFS_Last_cluster ( MQX_FILE_PTR mfs_fd_ptr ) { MFS_DRIVE_STRUCT_PTR drive_ptr; uint_32 last_cluster; uint_32 error_code; error_code = MFS_lock_dos_disk( mfs_fd_ptr, &drive_ptr ); if ( error_code != MFS_NO_ERROR ) { return error_code; } last_cluster = drive_ptr->LAST_CLUSTER; MFS_unlock(drive_ptr,FALSE); return(last_cluster); }
_mfs_error MFS_Get_file_attributes ( MQX_FILE_PTR mfs_fd_ptr, /*[IN] pathname of the file */ char _PTR_ pathname, uchar_ptr attribute_ptr ) { MFS_DRIVE_STRUCT_PTR drive_ptr; MFS_DIR_ENTRY_PTR dir_entry_ptr; uint_32 dir_cluster,dir_index; _mfs_error error_code; uchar attribute; uint_32 prev_cluster= CLUSTER_INVALID; if ( (pathname == NULL) || (*pathname == '\0') ) { return MFS_INVALID_PARAMETER; } error_code = MFS_lock_dos_disk( mfs_fd_ptr, &drive_ptr ); if ( error_code != MFS_NO_ERROR ) { return(error_code); } dir_entry_ptr = MFS_Find_entry_on_disk(drive_ptr, pathname, &error_code, &dir_cluster, &dir_index, &prev_cluster); /* ** When a function locks MFS device, on any error it should not return ** without unlocking it. This can create a deadlock. */ if ( error_code == MFS_NO_ERROR ) { attribute = dtohc(dir_entry_ptr->ATTRIBUTE); *attribute_ptr = attribute; } MFS_unlock(drive_ptr,FALSE); return(error_code); }
uint_32 MFS_Bad_clusters ( MQX_FILE_PTR mfs_fd_ptr ) { MFS_DRIVE_STRUCT_PTR drive_ptr; uint_32 last_cluster; uint_32 k; uint_32 bad_slots; uint_32 error_code; uint_32 cluster_status; bad_slots = 0; error_code = MFS_lock_dos_disk( mfs_fd_ptr, &drive_ptr ); if ( error_code != MFS_NO_ERROR ) { return error_code; } last_cluster = drive_ptr->LAST_CLUSTER; for ( k = CLUSTER_MIN_GOOD; k <= last_cluster; k++ ) { error_code = MFS_get_cluster_from_fat(drive_ptr, k, &cluster_status); if ( error_code != MFS_NO_ERROR ) { break; } else if ( cluster_status == CLUSTER_BAD ) { bad_slots++; } } MFS_unlock(drive_ptr,FALSE); return(bad_slots); }
_mfs_error MFS_Get_volume ( MFS_DRIVE_STRUCT_PTR drive_ptr, char *volume_name /*[OUT] name of the volune */ ) { MFS_DIR_ENTRY_PTR dir_entry_ptr; _mfs_error error_code; uint32_t vol_cluster, vol_index, i; char *disk_vol_name; uint32_t prev_cluster= CLUSTER_INVALID; if ( volume_name == NULL ) { return( MFS_INVALID_PARAMETER ); } error_code = MFS_lock_dos_disk(drive_ptr); if ( !error_code ) { vol_cluster = ROOT_CLUSTER(drive_ptr); vol_index = 0; dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, NULL, &vol_cluster, &vol_index, &prev_cluster, MFS_ATTR_VOLUME_NAME, &error_code); if ( dir_entry_ptr ) { disk_vol_name = dir_entry_ptr->NAME; for ( i = 0 ; i < SFILENAME_SIZE - 1; i++ ) { *volume_name++ = *disk_vol_name++; } } *volume_name = '\0'; } MFS_unlock(drive_ptr,FALSE); return( error_code ); }
_mfs_error MFS_Get_volume ( MQX_FILE_PTR mfs_fd_ptr, /*[IN] pointer to the file struct returned by fopen("MFS...:",..); */ char_ptr volume_name /*[OUT] name of the volune */ ) { MFS_DRIVE_STRUCT_PTR drive_ptr; MFS_DIR_ENTRY_PTR dir_entry_ptr; _mfs_error error_code; uint_32 vol_cluster, vol_index, i; char_ptr disk_vol_name; uint_32 prev_cluster= CLUSTER_INVALID; if ( volume_name == NULL ) { return( MFS_INVALID_PARAMETER ); } error_code = MFS_lock_dos_disk(mfs_fd_ptr, &drive_ptr); if ( !error_code ) { vol_cluster = ROOT_CLUSTER(drive_ptr); vol_index = 0; dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, NULL, &vol_cluster, &vol_index, &prev_cluster, MFS_ATTR_VOLUME_NAME, &error_code); if ( dir_entry_ptr ) { disk_vol_name = dir_entry_ptr->NAME; for ( i = 0 ; i < SFILENAME_SIZE - 1; i++ ) { *volume_name++ = *disk_vol_name++; } } *volume_name = '\0'; } MFS_unlock(drive_ptr,FALSE); return( error_code ); }
int32_t MFS_Close_file ( MFS_HANDLE_PTR handle, MFS_DRIVE_STRUCT_PTR drive_ptr ) { TIME_STRUCT time; DATE_STRUCT clk_time; _mfs_error error_code; error_code = MFS_lock_dos_disk( drive_ptr ); if ( error_code != MFS_NO_ERROR ) { return error_code; } #if !MFSCFG_READ_ONLY #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (drive_ptr)) { error_code = MFS_DISK_IS_WRITE_PROTECTED; } #endif if ((handle->TOUCHED) && (error_code == MFS_NO_ERROR)) { _time_get(&time); _time_to_date(&time, &clk_time); NORMALIZE_DATE(&clk_time); mqx_htods(handle->DIR_ENTRY.TIME, PACK_TIME(clk_time)); mqx_htods(handle->DIR_ENTRY.DATE, PACK_DATE(clk_time)); error_code = MFS_Update_entry(drive_ptr, handle); } #endif MFS_Free_handle(drive_ptr, handle); MFS_unlock(drive_ptr,TRUE); return(int32_t) error_code; }
uint32_t MFS_Write ( MFS_HANDLE_PTR handle, MFS_DRIVE_STRUCT_PTR drive_ptr, uint32_t num_bytes, /*[IN] number of bytes to be written */ char *buffer_address, /*[IN/OUT] bytes are written from this buffer */ _mfs_error_ptr error_ptr /*[IN/OUT] error code is written to this address */ ) { uint32_t bytes_written; uint32_t copy_size; uint32_t cluster_offset; uint32_t sector_number, sector_index; uint32_t sector_offset; uint32_t whole_sectors; uint32_t cont_sectors; uint32_t proc_sectors; _mfs_error error, temp_error; uint32_t file_size; uint32_t next_cluster; bool need_hwread; uint32_t location; uint32_t num_zeros; uint32_t zeros_written; uint32_t zero_size; #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (drive_ptr)) { MFS_set_error_and_return(error_ptr,MFS_DISK_IS_WRITE_PROTECTED,0); } #endif if ( buffer_address == NULL ) { MFS_set_error_and_return(error_ptr,MFS_INVALID_PARAMETER,0); } if ( num_bytes == 0 ) { MFS_set_error_and_return(error_ptr,MFS_NO_ERROR,0); } error = MFS_lock_dos_disk( drive_ptr ); if ( error != MFS_NO_ERROR ) { MFS_set_error_and_return(error_ptr,error,0); } if ( handle->ACCESS == MFS_ACCESS_READ_ONLY ) { MFS_unlock(drive_ptr,FALSE); MFS_set_error_and_return(error_ptr,MFS_ACCESS_DENIED,0); } /* ** Setup the current cluster. If this is the first time writing to the file, a cluster needs to be added. */ if ( handle->CURRENT_CLUSTER == 0 ) { handle->PREVIOUS_CLUSTER = 0; handle->CURRENT_CLUSTER = clustoh(handle->DIR_ENTRY.HFIRST_CLUSTER, handle->DIR_ENTRY.LFIRST_CLUSTER); if ( handle->CURRENT_CLUSTER==0 ) { next_cluster = MFS_Find_unused_cluster_from(drive_ptr,drive_ptr->NEXT_FREE_CLUSTER); if ( next_cluster != CLUSTER_INVALID ) { clustod(handle->DIR_ENTRY.HFIRST_CLUSTER, handle->DIR_ENTRY.LFIRST_CLUSTER, next_cluster); handle->TOUCHED = 1; error = MFS_Put_fat(drive_ptr, next_cluster, CLUSTER_EOF); if ( error == MFS_NO_ERROR ) { handle->CURRENT_CLUSTER = next_cluster; } else { MFS_unlock(drive_ptr,FALSE); MFS_set_error_and_return(error_ptr,error,0); } } else { MFS_unlock(drive_ptr,FALSE); MFS_set_error_and_return(error_ptr,MFS_DISK_FULL,0); } } } else if ( handle->CURRENT_CLUSTER == CLUSTER_EOF ) { error = MFS_Add_cluster_to_chain(drive_ptr, handle->PREVIOUS_CLUSTER, &handle->CURRENT_CLUSTER); if ( MFS_NO_ERROR != error ) { MFS_unlock(drive_ptr,FALSE); MFS_set_error_and_return(error_ptr,error,0); } } else if ( handle->CURRENT_CLUSTER > drive_ptr->LAST_CLUSTER ) { MFS_unlock(drive_ptr,FALSE); MFS_set_error_and_return(error_ptr,MFS_DISK_FULL,0); } /* Make sure location (local variable) never points behind the end of file */ file_size = mqx_dtohl(handle->DIR_ENTRY.FILE_SIZE); location = (handle->LOCATION > file_size) ? file_size : handle->LOCATION; /* Calculate sector number and offsets within cluster and sector */ cluster_offset = OFFSET_WITHIN_CLUSTER(location); sector_index = CLUSTER_OFFSET_TO_SECTOR(cluster_offset); sector_number = CLUSTER_TO_SECTOR(handle->CURRENT_CLUSTER) + sector_index; sector_offset = OFFSET_WITHIN_SECTOR(location); /* Calculate possible gap to fill in by zeros if writing behind the end of file */ num_zeros = handle->LOCATION - location; zeros_written = 0; bytes_written = 0; /* Write zeros to fill in gap if LOCATION points behind the end of file */ while (zeros_written < num_zeros) { /* If offset is non-zero, then reading the data is required */ error = MFS_Read_data_sector(drive_ptr, handle, sector_number, sector_offset != 0); if ( error != MFS_NO_ERROR ) break; /* Zero the buffer */ zero_size = min(num_zeros-zeros_written, drive_ptr->BPB.SECTOR_SIZE-sector_offset); _mem_zero(&drive_ptr->DATA_SECTOR_PTR[sector_offset], zero_size); drive_ptr->DATA_SECTOR_DIRTY = TRUE; if ( drive_ptr->WRITE_CACHE_POLICY == MFS_WRITE_THROUGH_CACHE ) { error = MFS_Flush_data_sector_buffer(drive_ptr); if ( error != MFS_NO_ERROR ) break; } zeros_written += zero_size; sector_offset += zero_size; /* ** Check to see if we need to advance to the next sector, which has ** the side effect of increasing the cluster number if required. */ if ( sector_offset >= drive_ptr->BPB.SECTOR_SIZE ) { temp_error = MFS_next_data_sector(drive_ptr, handle, §or_index, §or_number); if (temp_error == MFS_EOF) { /* Always allocate new cluster, there is something to be written for sure */ error = MFS_Add_cluster_to_chain(drive_ptr, handle->PREVIOUS_CLUSTER, &handle->CURRENT_CLUSTER); if ( MFS_NO_ERROR == error ) { sector_number = CLUSTER_TO_SECTOR(handle->CURRENT_CLUSTER); sector_index = 0; } } else { error = temp_error; } sector_offset = 0; } } /* Write partial sector if sector_offset is non-zero */ if ((sector_offset != 0) && (error == MFS_NO_ERROR)) { /* Offset is non-zero, reading the data is required */ error = MFS_Read_data_sector(drive_ptr, handle, sector_number, TRUE); if (error == MFS_NO_ERROR) { /* The requested lenght of data may span the sector to it's end */ copy_size = min(num_bytes, drive_ptr->BPB.SECTOR_SIZE-sector_offset); _mem_copy(buffer_address, &drive_ptr->DATA_SECTOR_PTR[sector_offset], copy_size); drive_ptr->DATA_SECTOR_DIRTY = TRUE; if (drive_ptr->WRITE_CACHE_POLICY == MFS_WRITE_THROUGH_CACHE) { error = MFS_Flush_data_sector_buffer(drive_ptr); } if (error == MFS_NO_ERROR) { bytes_written = copy_size; /* ** Check to see if we need to advance to the next sector, which has ** the side effect of increasing the cluster number if required. */ if ((sector_offset + bytes_written) >= drive_ptr->BPB.SECTOR_SIZE) { temp_error = MFS_next_data_sector(drive_ptr, handle, §or_index, §or_number); /* Only an error if we are not done writing and can't extend the chain */ if (bytes_written < num_bytes) { if (temp_error == MFS_EOF) { /* Allocate new cluster */ error = MFS_Add_cluster_to_chain(drive_ptr, handle->PREVIOUS_CLUSTER, &handle->CURRENT_CLUSTER); /* Update sector_number and index unconditionally - if there was an error the value is never used anyways. */ sector_number = CLUSTER_TO_SECTOR(handle->CURRENT_CLUSTER); sector_index = 0; } else { error = temp_error; } } } } } } /* Check whether the application buffer is properly aligned */ if ((((uint32_t)buffer_address+bytes_written) & drive_ptr->ALIGNMENT_MASK) == 0) { /* Yes, use zero copy approach */ whole_sectors = (num_bytes - bytes_written) >> drive_ptr->SECTOR_POWER; while ((whole_sectors > 0) && (error == MFS_NO_ERROR)) { cont_sectors = drive_ptr->BPB.SECTORS_PER_CLUSTER - sector_index; if (cont_sectors > whole_sectors) cont_sectors = whole_sectors; error = MFS_Write_device_sectors(drive_ptr, sector_number, cont_sectors, MFSCFG_MAX_WRITE_RETRIES, buffer_address+bytes_written, &proc_sectors); if (proc_sectors > 0) { bytes_written += proc_sectors * drive_ptr->BPB.SECTOR_SIZE; whole_sectors -= proc_sectors; /* Advance to next unprocessed sector */ sector_index += proc_sectors - 1; temp_error = MFS_next_data_sector(drive_ptr, handle, §or_index, §or_number); /* Go on only if we are not done writing yet */ if ((error == MFS_NO_ERROR) && (bytes_written < num_bytes)) { if (temp_error == MFS_EOF) { /* Allocate new cluster */ error = MFS_Add_cluster_to_chain(drive_ptr, handle->PREVIOUS_CLUSTER, &handle->CURRENT_CLUSTER); /* Update sector_number and index unconditionally - if there was an error the value is never used anyways. */ sector_number = CLUSTER_TO_SECTOR(handle->CURRENT_CLUSTER); sector_index = 0; } else { error = temp_error; } } } } }
_mfs_error MFS_Set_volume ( MFS_DRIVE_STRUCT_PTR drive_ptr, char *volume_name /*[IN] name to use for the volune */ ) { MFS_DIR_ENTRY_PTR dir_entry_ptr; _mfs_error error_code; uint32_t vol_cluster, vol_index; uint32_t prev_cluster= CLUSTER_INVALID; if ( volume_name == NULL ) { return( MFS_INVALID_PARAMETER ); } if ( *volume_name == '\0' ) { return( MFS_INVALID_PARAMETER ); } #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (drive_ptr)) { return MFS_DISK_IS_WRITE_PROTECTED; } #endif error_code = MFS_lock_dos_disk(drive_ptr); if ( !error_code ) { vol_cluster = ROOT_CLUSTER(drive_ptr); vol_index = 0; dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, NULL, &vol_cluster, &vol_index, &prev_cluster, MFS_ATTR_VOLUME_NAME, &error_code); if ( dir_entry_ptr ) { MFS_Expand_dotfile(volume_name, dir_entry_ptr->NAME); *dir_entry_ptr->ATTRIBUTE = MFS_ATTR_VOLUME_NAME; drive_ptr->DIR_SECTOR_DIRTY = TRUE; } else if ( !error_code ) { vol_cluster = ROOT_CLUSTER(drive_ptr); vol_index = 0; dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &vol_cluster, &vol_index, &prev_cluster, MFS_ATTR_ANY, &error_code); if ( dir_entry_ptr ) { MFS_Expand_dotfile(volume_name, dir_entry_ptr->NAME); *dir_entry_ptr->ATTRIBUTE = MFS_ATTR_VOLUME_NAME; drive_ptr->DIR_SECTOR_DIRTY = TRUE; } } } MFS_unlock(drive_ptr,TRUE); return( error_code ); }
_mfs_error MFS_Find_first_file ( MFS_DRIVE_STRUCT_PTR drive_ptr, unsigned char attribute, /*[IN] type of file to find, Search attributes */ char *pathname, /*[IN] optionally the directory and filename to search for */ MFS_SEARCH_DATA_PTR transfer_ptr /*[IN] address of search data block into which the results of the search are put */ ) { MFS_INTERNAL_SEARCH_PTR internal_search_ptr; char *temp_dirname; char *temp_filename; uint32_t current_cluster; _mfs_error error_code; uint32_t i; char c; if ( (pathname==NULL) || (*pathname=='\0') ) { return MFS_INVALID_PARAMETER; } if ( transfer_ptr == NULL ) { return MFS_INVALID_MEMORY_BLOCK_ADDRESS; } error_code = MFS_alloc_2paths(&temp_dirname,&temp_filename); if ( error_code != MFS_NO_ERROR ) { return( error_code ); } error_code = MFS_lock_dos_disk( drive_ptr ); if ( error_code != MFS_NO_ERROR ) { MFS_free_path(temp_dirname); MFS_free_path(temp_filename); return error_code; } _mem_zero(transfer_ptr, sizeof (MFS_SEARCH_DATA)); transfer_ptr->DRIVE_PTR = drive_ptr; MFS_Parse_pathname(temp_dirname, temp_filename, pathname); current_cluster = drive_ptr->CUR_DIR_CLUSTER; current_cluster = MFS_Find_directory(drive_ptr, temp_dirname, current_cluster); if ( current_cluster == CLUSTER_INVALID ) { error_code = MFS_PATH_NOT_FOUND; } else { /* ** The internal search is only initialised if the directory exists. */ internal_search_ptr = &transfer_ptr->INTERNAL_SEARCH_DATA; internal_search_ptr->CURRENT_CLUSTER = current_cluster; internal_search_ptr->PREV_CLUSTER = CLUSTER_INVALID; internal_search_ptr->DIR_ENTRY_INDEX = 0; MFS_Expand_wildcard(temp_filename, internal_search_ptr->FILENAME); internal_search_ptr->FULLNAME = temp_filename; i = _strnlen(pathname, PATHNAME_SIZE + FILENAME_SIZE + 1); c = pathname[--i]; while ( (c != '\\') && (c != '/') && (c != ':') && i ) { i--; c = pathname[i]; } if ( i || c == '\\' || c == '/' ) { i++; } internal_search_ptr->SRC_PTR = pathname + i; internal_search_ptr->ATTRIBUTE = attribute; error_code = MFS_Find_next_slave(drive_ptr, transfer_ptr); } MFS_free_path(temp_dirname); MFS_free_path(temp_filename); MFS_unlock(drive_ptr,FALSE); return(error_code); }
_mfs_error MFS_Create_subdir ( MFS_DRIVE_STRUCT_PTR drive_ptr, char *pathname /*[IN] pathname of the directory to be created */ ) { MFS_DIR_ENTRY_PTR dir_entry_ptr; uint32_t dir_cluster; uint32_t parent_cluster; uint32_t free_cluster; uint32_t dir_index; _mfs_error error_code; char *temp_dirname; char *temp_filename; if ( (pathname == NULL) || (*pathname == '\0') ) { return MFS_INVALID_PARAMETER; } #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (drive_ptr)) { return MFS_DISK_IS_WRITE_PROTECTED; } #endif error_code = MFS_alloc_2paths(&temp_dirname,&temp_filename); if ( error_code != MFS_NO_ERROR ) { return( error_code ); } error_code = MFS_lock_dos_disk( drive_ptr ); if ( error_code != MFS_NO_ERROR ) { MFS_free_path(temp_dirname); MFS_free_path(temp_filename); return error_code; } MFS_Parse_pathname (temp_dirname, temp_filename, pathname); dir_cluster = drive_ptr->CUR_DIR_CLUSTER; parent_cluster = MFS_Find_directory (drive_ptr, temp_dirname, dir_cluster); dir_cluster = parent_cluster; if ( MFS_is_valid_lfn(temp_filename) ) { if ( dir_cluster != CLUSTER_INVALID ) { /* ** We'll obtain a cluster for the new directory first. If we ** cannot create the directory afterwards, it is easier to re-free ** the cluster than to remove the new entry. */ free_cluster = MFS_Find_unused_cluster_from(drive_ptr, drive_ptr->NEXT_FREE_CLUSTER); if ( free_cluster != CLUSTER_INVALID ) { error_code = MFS_Clear_cluster(drive_ptr, free_cluster); if ( error_code ) { MFS_unlock(drive_ptr,TRUE); MFS_free_path(temp_dirname); MFS_free_path(temp_filename); return( error_code ); } error_code = MFS_Put_fat(drive_ptr, free_cluster, CLUSTER_EOF); dir_entry_ptr = MFS_Create_directory_entry(drive_ptr, temp_filename, MFS_ATTR_DIR_NAME, &dir_cluster, &dir_index, &error_code); if ( error_code == MFS_NO_ERROR ) { clustod(dir_entry_ptr->HFIRST_CLUSTER, dir_entry_ptr->LFIRST_CLUSTER, free_cluster); drive_ptr->DIR_SECTOR_DIRTY = TRUE; /* ** We shall now create the "." and ".." entries. */ dir_cluster = free_cluster; dir_entry_ptr = MFS_Create_directory_entry(drive_ptr,".", MFS_ATTR_DIR_NAME, &dir_cluster, &dir_index, &error_code); if ( error_code == MFS_NO_ERROR ) { clustod(dir_entry_ptr->HFIRST_CLUSTER, dir_entry_ptr->LFIRST_CLUSTER, free_cluster); drive_ptr->DIR_SECTOR_DIRTY = TRUE; dir_entry_ptr = MFS_Create_directory_entry(drive_ptr,"..", MFS_ATTR_DIR_NAME, &dir_cluster, &dir_index, &error_code); if ( error_code == MFS_NO_ERROR ) { if ( drive_ptr->FAT_TYPE == MFS_FAT32 ) { if ( drive_ptr->BPB32.ROOT_CLUSTER == parent_cluster ) { /* ** Even though the FAT32 root sector can be ** anywhere, it is identified as 0 when referenced ** through a directory entry */ parent_cluster = 0; } } clustod(dir_entry_ptr->HFIRST_CLUSTER, dir_entry_ptr->LFIRST_CLUSTER, parent_cluster); drive_ptr->DIR_SECTOR_DIRTY = TRUE; } } } else { MFS_Put_fat(drive_ptr, free_cluster, CLUSTER_UNUSED); } } else { error_code = MFS_DISK_FULL; } } else { error_code = MFS_PATH_NOT_FOUND; } } else if ( MFS_lfn_dirname_valid(temp_filename) ) { if ( dir_cluster ) { error_code = MFS_FILE_EXISTS; } else { error_code = MFS_CANNOT_CREATE_DIRECTORY; } } else { error_code = MFS_INVALID_PARAMETER; } MFS_free_path(temp_dirname); MFS_free_path(temp_filename); MFS_unlock(drive_ptr,TRUE); return(error_code); }
_mfs_error MFS_Change_current_dir ( MFS_DRIVE_STRUCT_PTR drive_ptr, char *pathname /*[IN] pathname of the directory to become the current dir */ ) { uint32_t dir_cluster; uint16_t length; _mfs_error error_code; char *directory; char *temp_cur; register char *src, *dest, *dest_start; if ( (pathname == NULL) || (*pathname == '\0') ) { return MFS_INVALID_PARAMETER; } error_code = MFS_alloc_2paths(&directory,&temp_cur); if ( error_code != MFS_NO_ERROR ) { return( error_code ); } error_code = MFS_lock_dos_disk( drive_ptr ); if ( error_code != MFS_NO_ERROR ) { MFS_free_path(directory); MFS_free_path(temp_cur); return error_code; } dir_cluster = drive_ptr->CUR_DIR_CLUSTER; dir_cluster = MFS_Find_directory(drive_ptr, pathname, dir_cluster); if ( dir_cluster != CLUSTER_INVALID ) { src = pathname; dest = temp_cur; if ( *src == '\\' || *src == '/' ) { temp_cur[0] = '\\'; temp_cur[1] = '\0'; src++; } else { strcpy (temp_cur, drive_ptr->CURRENT_DIR); dest = temp_cur + strlen(temp_cur) - 1; } dest_start = temp_cur; length = strlen(dest_start); while ( src ) { if ( *src ) { src = MFS_Parse_next_filename(src, directory); if ( src != NULL ) { MFS_strupr(directory); } if ( directory[0] == '.' && directory[1] == '.' ) { if ( dest != dest_start ) { while ( dest != dest_start && *dest != '\\' ) { dest--; } /* Erase the previous backslash, unless it is the ** first (root directory). */ if ( dest != dest_start ) { *dest-- = '\0'; } else { *(dest+1) = '\0'; } } else { /* ** The check for underflow is redundant, because the path ** has been found already. */ error_code = MFS_PATH_NOT_FOUND; break; } } else if ( directory[0] && directory[0] != '.' ) { if ( *dest != '\\' ) { *(++dest) = '\\'; length++; } length += strlen(directory); if ( length < sizeof (drive_ptr->CURRENT_DIR) ) { strcpy (++dest, directory); dest = temp_cur + length - 1; } else { error_code = MFS_INVALID_LENGTH_IN_DISK_OPERATION; break; } } } else { break; } } if ( error_code == MFS_NO_ERROR ) { strcpy (drive_ptr->CURRENT_DIR, dest_start); drive_ptr->CUR_DIR_CLUSTER = dir_cluster; } } else { error_code = MFS_PATH_NOT_FOUND; } MFS_free_path(directory); MFS_free_path(temp_cur); MFS_unlock(drive_ptr,FALSE); return(error_code); }
uint32_t MFS_Move_file_pointer ( MFS_HANDLE_PTR handle, MFS_DRIVE_STRUCT_PTR drive_ptr, _mfs_error_ptr error_ptr /*[IN/OUT] resulting error code is written to this address*/ ) { uint32_t position_after_seek, position_before_seek; uint32_t current_cluster, previous_cluster, first_cluster, skip_clusters, k; _mfs_error error_code; error_code = MFS_lock_dos_disk( drive_ptr ); if ( error_code != MFS_NO_ERROR ) { if ( error_ptr != NULL ) { *error_ptr = error_code; } return 0; } position_after_seek = handle->LOCATION; MFS_LOG(printf("seek to %d\n",position_after_seek)); /* ** Cannot move ahead of the beginning of the file; force beginning. */ if ( error_code == MFS_NO_ERROR ) { /* ** There are four cases ** ** 1) Seeking to beginning of file (position_after_seek=0, cluster=0) ** 2) No change in position (position_after_seek==position_before_seek) ** 2) Seeking ahead of current file pointer ** 3) Seeking behind current file pointer */ /* ** Cannot move beyond the end of file ! */ if ( position_after_seek> mqx_dtohl(handle->DIR_ENTRY.FILE_SIZE) ) // + 1 { position_after_seek = mqx_dtohl(handle->DIR_ENTRY.FILE_SIZE); // - 1 error_code = MFS_EOF; } current_cluster = 0; previous_cluster = 0; first_cluster = clustoh(handle->DIR_ENTRY.HFIRST_CLUSTER, handle->DIR_ENTRY.LFIRST_CLUSTER); MFS_LOG(printf("first_cluster = %d\n",first_cluster)); /* ** Set the current_cluster correctly. ** If we're moving ahead, don't start from the beginning. */ position_before_seek = CLUSTER_BOUNDARY(handle->SAVED_POSITION); if ( handle->CURRENT_CLUSTER==0 ) { handle->CURRENT_CLUSTER = first_cluster; handle->PREVIOUS_CLUSTER = 0; position_before_seek = 0; } if ( position_after_seek == 0 ) { current_cluster = first_cluster; previous_cluster = 0; } else if ( position_after_seek == position_before_seek ) { current_cluster = handle->CURRENT_CLUSTER; previous_cluster = handle->PREVIOUS_CLUSTER; } else { if ( position_after_seek < position_before_seek ) { position_before_seek = 0; current_cluster = first_cluster; previous_cluster = 0; } else { current_cluster = handle->CURRENT_CLUSTER; previous_cluster = handle->PREVIOUS_CLUSTER; } MFS_LOG(printf("current cluster = %d\n",current_cluster)); if ( current_cluster && (current_cluster!=CLUSTER_EOF) ) { /* ** How many clusters do we need to skip? */ skip_clusters = (position_after_seek - position_before_seek) >> drive_ptr->CLUSTER_POWER_BYTES; for ( k = 0; k < skip_clusters; k++ ) { previous_cluster = current_cluster; error_code = MFS_get_cluster_from_fat(drive_ptr, previous_cluster, ¤t_cluster); if ( error_code != MFS_NO_ERROR ) { break; } if ( current_cluster==CLUSTER_EOF ) { error_code = MFS_EOF; break; } else if ( (current_cluster < CLUSTER_MIN_GOOD) || (current_cluster > drive_ptr->LAST_CLUSTER) ) { error_code = MFS_BAD_DISK_UNIT; break; } MFS_LOG(printf("skip, current cluster = %d\n",current_cluster)); } } else { error_code = MFS_EOF; } }
void *MFS_Create_temp_file ( MFS_DRIVE_STRUCT_PTR drive_ptr, unsigned char attr, /*[IN] attribute to be given to the file when it is created */ char *pathname, /*[IN] provides the directory path where the file is to be created, **[OUT] the file name is appended to the directory name */ _mfs_error_ptr error_ptr /*[OUT] Pointer for the MFS ERROR CODE location */ ) { MFS_HANDLE_PTR handle; MFS_DIR_ENTRY_PTR dir_entry_ptr; _mfs_error error_code; uint32_t dir_cluster, dir_index; uint16_t trial; char *last_char; uint16_t pathlen; unsigned char access; char *temp_file; #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (drive_ptr)) { *error_ptr = MFS_DISK_IS_WRITE_PROTECTED; return NULL; } #endif trial = 0; error_code = MFS_FILE_NOT_FOUND; handle = NULL; if ( (pathname == NULL) || (*pathname == '\0') ) { *error_ptr = MFS_INVALID_PARAMETER; return( NULL ); } *error_ptr = MFS_alloc_path(&temp_file); if ( *error_ptr ) { return( NULL ); } *error_ptr = MFS_lock_dos_disk( drive_ptr ); if ( *error_ptr != MFS_NO_ERROR ) { MFS_free_path(temp_file); return NULL; } attr &= (MFS_ATTR_READ_ONLY | MFS_ATTR_HIDDEN_FILE | MFS_ATTR_SYSTEM_FILE | MFS_ATTR_ARCHIVE | MFS_ATTR_VOLUME_NAME); attr |= MFS_ATTR_ARCHIVE; access = (attr & MFS_ATTR_READ_ONLY) ? MFS_ACCESS_READ_ONLY : MFS_ACCESS_READ_WRITE; dir_cluster = drive_ptr->CUR_DIR_CLUSTER; dir_cluster = MFS_Find_directory(drive_ptr, pathname, dir_cluster); if ( dir_cluster == CLUSTER_INVALID ) { error_code = MFS_PATH_NOT_FOUND; } else { pathlen = strlen (pathname); last_char = pathname + pathlen; if ( pathlen ) { last_char--; } do { sprintf(temp_file, (*last_char == '\\' || *last_char == '/' || pathlen == 0) ? "%sTMP%05.5lu.@@@" : "%s\\TMP%05.5lu.@@@", pathname, (uint32_t) trial); dir_entry_ptr = MFS_Create_entry_slave(drive_ptr, attr, temp_file, &dir_cluster, &dir_index, &error_code, FALSE); trial++; } while ( (error_code == MFS_FILE_EXISTS) && (trial < MFSCFG_FIND_TEMP_TRIALS) ); if ( error_code == MFS_NO_ERROR ) { handle = MFS_Get_handle(drive_ptr,dir_entry_ptr); if ( handle ) { _mem_copy (temp_file, pathname, strlen(temp_file) + 1); handle->DIR_CLUSTER = dir_cluster; handle->DIR_INDEX = dir_index; handle->ACCESS = access; handle->CURRENT_CLUSTER = 0; handle->PREVIOUS_CLUSTER = 0; } else { error_code = MFS_INSUFFICIENT_MEMORY; } } } MFS_free_path(temp_file); MFS_unlock(drive_ptr,FALSE); if ( error_ptr ) { *error_ptr = error_code; } return((void *) handle); }
void *MFS_Open_file ( MFS_DRIVE_STRUCT_PTR drive_ptr, char *pathname, /*[IN] directory and filename of the file to be opened */ unsigned char access, /*[IN] type of access required: read, write or read/write*/ uint32_t *error_ptr /*[IN/OUT] error code is written to this address */ ) { MFS_DIR_ENTRY_PTR dir_entry_ptr; MFS_HANDLE_PTR handle,open_handle; uint32_t dir_cluster, dir_index; _mfs_error error_code; uint32_t prev_cluster= CLUSTER_INVALID; if ( (pathname == NULL) || (*pathname == '\0') ) { if ( error_ptr != NULL ) { *error_ptr = MFS_INVALID_PARAMETER; } return NULL; } error_code = MFS_lock_dos_disk( drive_ptr ); if ( error_code != MFS_NO_ERROR ) { if ( error_ptr != NULL ) { *error_ptr = error_code; } return NULL; } handle = NULL; dir_entry_ptr = MFS_Find_entry_on_disk(drive_ptr, pathname, &error_code, &dir_cluster, &dir_index, &prev_cluster); if ( error_code == MFS_NO_ERROR ) { if ( mqx_dtohc(dir_entry_ptr->ATTRIBUTE) & (MFS_ATTR_DIR_NAME | MFS_ATTR_VOLUME_NAME) ) { error_code = MFS_WRITE_FAULT; } else if ( (mqx_dtohc(dir_entry_ptr->ATTRIBUTE) & MFS_ATTR_READ_ONLY) && ((access == MFS_ACCESS_WRITE_ONLY) || (access == MFS_ACCESS_READ_WRITE)) ) { error_code = MFS_ACCESS_DENIED; } else { // Check to see if the file is already opened open_handle = MFS_Find_handle(drive_ptr, dir_cluster, dir_index); if (open_handle) { // If we are opening to write, the file can't already be opened. if ((access == MFS_ACCESS_WRITE_ONLY) || (access == MFS_ACCESS_READ_WRITE)) { error_code = MFS_SHARING_VIOLATION; } // And if we the file is already opened, it can't be opened to write. // Note that if it is opened for write, it will be the only instance on the list if ((handle->ACCESS == MFS_ACCESS_WRITE_ONLY) || (handle->ACCESS == MFS_ACCESS_READ_WRITE)) { error_code = MFS_SHARING_VIOLATION; } } if (error_code == MFS_NO_ERROR) { handle = MFS_Get_handle(drive_ptr,dir_entry_ptr); if ( handle != NULL ) { handle->ACCESS = access; handle->CURRENT_CLUSTER = 0; handle->PREVIOUS_CLUSTER = 0; handle->DIR_CLUSTER = dir_cluster; handle->DIR_INDEX = dir_index; } else { error_code = MFS_INSUFFICIENT_MEMORY; } } } } MFS_unlock(drive_ptr,FALSE); if ( error_ptr ) { *error_ptr = error_code; } return((void *) handle); }
_mfs_error MFS_Delete_file ( MQX_FILE_PTR mfs_fd_ptr, /*[IN] the MFS device on which to operate */ char_ptr pathname /*[IN] directory and file name of the file to delete */ ) { MFS_DRIVE_STRUCT_PTR drive_ptr; MFS_DIR_ENTRY_PTR dir_entry_ptr; _mfs_error error_code, saved_code = 0; uint_32 dir_cluster, dir_index; uint_32 first_cluster; uint_32 prev_cluster= CLUSTER_INVALID; if ( (pathname == NULL) || (*pathname == '\0') ) { return MFS_INVALID_PARAMETER; } #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (mfs_fd_ptr, NULL)) { return MFS_DISK_IS_WRITE_PROTECTED; } #endif error_code = MFS_lock_dos_disk( mfs_fd_ptr, &drive_ptr ); if ( error_code != MFS_NO_ERROR ) { return error_code; } dir_entry_ptr = MFS_Find_entry_on_disk(drive_ptr, pathname, &error_code, &dir_cluster, &dir_index, &prev_cluster); if ( dir_entry_ptr != NULL ) { if ( dtohc(dir_entry_ptr->ATTRIBUTE) & (MFS_ATTR_DIR_NAME | MFS_ATTR_VOLUME_NAME | MFS_ATTR_READ_ONLY) ) { error_code = MFS_ACCESS_DENIED; } else { first_cluster = clustoh(dir_entry_ptr->HFIRST_CLUSTER, dir_entry_ptr->LFIRST_CLUSTER); if ( first_cluster ) { saved_code = MFS_Release_chain(drive_ptr, first_cluster); if ( saved_code != MFS_LOST_CHAIN && saved_code != MFS_NO_ERROR ) { MFS_unlock(drive_ptr,TRUE); return(saved_code); } } /* ** Mark all open files with the same name as erased */ MFS_Delete_handles(drive_ptr, dir_entry_ptr->NAME, first_cluster); *dir_entry_ptr->NAME = MFS_DEL_FILE; drive_ptr->DIR_SECTOR_DIRTY = TRUE; error_code = MFS_remove_lfn_entries(drive_ptr,dir_cluster,dir_index, prev_cluster); } } MFS_unlock(drive_ptr,TRUE); if ( saved_code == MFS_LOST_CHAIN && error_code == MFS_NO_ERROR ) { error_code = saved_code; } return(error_code); }
void *MFS_Create_new_file ( MFS_DRIVE_STRUCT_PTR drive_ptr, unsigned char attr, /*[IN] attribute to be given to the new file */ char *pathname, /*[IN] directory and file name to be given to the new file */ _mfs_error_ptr error_ptr /*[IN/OUT] error code is written to this address */ ) { MFS_HANDLE_PTR handle; MFS_DIR_ENTRY_PTR dir_entry_ptr; uint32_t dir_cluster, dir_index; _mfs_error error_code; char access; #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (drive_ptr)) { *error_ptr = MFS_DISK_IS_WRITE_PROTECTED; return NULL; } #endif handle = NULL; error_code = MFS_NO_ERROR; if ( (pathname == NULL) || (*pathname == '\0') ) { *error_ptr = MFS_INVALID_PARAMETER; return( NULL ); } *error_ptr = MFS_lock_dos_disk( drive_ptr ); if ( *error_ptr != MFS_NO_ERROR ) { return NULL; } attr &= (MFS_ATTR_READ_ONLY | MFS_ATTR_HIDDEN_FILE | MFS_ATTR_SYSTEM_FILE | MFS_ATTR_ARCHIVE); attr |= MFS_ATTR_ARCHIVE; access = (attr & MFS_ATTR_READ_ONLY) ? MFS_ACCESS_READ_ONLY : MFS_ACCESS_READ_WRITE; dir_entry_ptr = MFS_Create_entry_slave(drive_ptr, attr, pathname, &dir_cluster, &dir_index, &error_code, FALSE); if ( error_code == MFS_NO_ERROR && dir_entry_ptr != NULL ) { handle = MFS_Get_handle(drive_ptr,dir_entry_ptr); if ( handle ) { handle->ACCESS = access; handle->DIR_CLUSTER = dir_cluster; handle->DIR_INDEX = dir_index; handle->CURRENT_CLUSTER = 0; handle->PREVIOUS_CLUSTER = 0; } else { error_code = MFS_INSUFFICIENT_MEMORY; } } MFS_unlock(drive_ptr,FALSE); if ( error_ptr ) { *error_ptr = error_code; } return((void *)handle); }
_mfs_error MFS_Remove_subdir ( MFS_DRIVE_STRUCT_PTR drive_ptr, char *pathname /*[IN] pathname of the directory to be removed */ ) { _mfs_error error_code, saved_error = 0; uint32_t dir_cluster, parent_cluster, dir_index; MFS_DIR_ENTRY_PTR dir_entry_ptr; uint32_t prev_cluster= CLUSTER_INVALID; uint32_t parent_prev_cluster= CLUSTER_INVALID; if ( (pathname == NULL) || (*pathname == '\0') ) { return MFS_INVALID_PARAMETER; } error_code = MFS_lock_dos_disk( drive_ptr ); if ( error_code != MFS_NO_ERROR ) { return error_code; } dir_entry_ptr = MFS_Find_entry_on_disk (drive_ptr, pathname, &error_code, &parent_cluster, &dir_index, &parent_prev_cluster); if ( dir_entry_ptr ) { if ( mqx_dtohc(dir_entry_ptr->ATTRIBUTE) & MFS_ATTR_DIR_NAME ) { dir_cluster = clustoh(dir_entry_ptr->HFIRST_CLUSTER, dir_entry_ptr->LFIRST_CLUSTER); if ( dir_cluster != drive_ptr->CUR_DIR_CLUSTER ) { dir_index = 2; /* Skip over '.' and '..' */ dir_entry_ptr = MFS_Find_directory_entry (drive_ptr, NULL, &dir_cluster, &dir_index, &prev_cluster, MFS_ATTR_ANY, &error_code); if ( dir_entry_ptr == NULL && !error_code ) { dir_index = 0; dir_entry_ptr = MFS_Find_entry_on_disk (drive_ptr, pathname, &error_code, &parent_cluster, &dir_index, &parent_prev_cluster); if ( dir_entry_ptr ) { *dir_entry_ptr->NAME = MFS_DEL_FILE; drive_ptr->DIR_SECTOR_DIRTY = TRUE; error_code = MFS_remove_lfn_entries(drive_ptr, parent_cluster, dir_index, parent_prev_cluster); if ( !error_code ) { saved_error = MFS_Release_chain(drive_ptr, dir_cluster); } } } else if ( dir_entry_ptr != NULL && !error_code ) { error_code = MFS_FILE_EXISTS; } } else { error_code = MFS_ATTEMPT_TO_REMOVE_CURRENT_DIR; } } else { error_code = MFS_WRITE_FAULT; } } else { error_code = MFS_PATH_NOT_FOUND; } MFS_unlock(drive_ptr,TRUE); if ( saved_error == MFS_LOST_CHAIN && error_code == MFS_NO_ERROR ) { error_code = saved_error; } return(error_code); }
void *MFS_Create_file ( MFS_DRIVE_STRUCT_PTR drive_ptr, unsigned char attr, /*[IN] attribute for created file*/ char *pathname, /*[IN] directory and filename of the file to be created */ _mfs_error_ptr error_ptr /*[IN/OUT] error code is written to this address */ ) { MFS_HANDLE_PTR handle; MFS_HANDLE_PTR next_handle; MFS_DIR_ENTRY_PTR dir_entry_ptr; TIME_STRUCT time; DATE_STRUCT clk_time; uint32_t dir_cluster; uint32_t dir_index; char access; _mfs_error error_code, saved_code = 0; if ( (pathname == NULL) || (*pathname == '\0') ) { *error_ptr = MFS_INVALID_PARAMETER; return( NULL ); } #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (drive_ptr)) { *error_ptr = MFS_DISK_IS_WRITE_PROTECTED; return NULL; } #endif error_code = MFS_lock_dos_disk( drive_ptr ); if ( error_code != MFS_NO_ERROR ) { *error_ptr = error_code; return( NULL ); } handle = NULL; attr &= (MFS_ATTR_READ_ONLY | MFS_ATTR_HIDDEN_FILE | MFS_ATTR_SYSTEM_FILE | MFS_ATTR_ARCHIVE | MFS_ATTR_VOLUME_NAME); attr |= MFS_ATTR_ARCHIVE; access = (attr & MFS_ATTR_READ_ONLY) ? MFS_ACCESS_READ_ONLY : MFS_ACCESS_READ_WRITE; dir_entry_ptr = MFS_Create_entry_slave(drive_ptr, attr, pathname, &dir_cluster, &dir_index, &error_code, TRUE); if ( (dir_entry_ptr != NULL) && !(attr & MFS_ATTR_VOLUME_NAME) ) { handle = MFS_Get_handle(drive_ptr,dir_entry_ptr); if ( handle != NULL ) { handle->DIR_CLUSTER = dir_cluster; handle->DIR_INDEX = dir_index; handle->ACCESS = access; handle->CURRENT_CLUSTER = 0; handle->PREVIOUS_CLUSTER = 0; /* ** If file exists, overwrite and set size to 0 */ if ( error_code == MFS_FILE_EXISTS ) { _time_get(&time); _time_to_date(&time, &clk_time); NORMALIZE_DATE(&clk_time); saved_code = MFS_Release_chain(drive_ptr, clustoh(handle->DIR_ENTRY.HFIRST_CLUSTER, handle->DIR_ENTRY.LFIRST_CLUSTER)); if ( saved_code == MFS_NO_ERROR || saved_code == MFS_LOST_CHAIN ) { clustod(handle->DIR_ENTRY.HFIRST_CLUSTER, handle->DIR_ENTRY.LFIRST_CLUSTER, 0); mqx_htodl(handle->DIR_ENTRY.FILE_SIZE, 0L); mqx_htodc(handle->DIR_ENTRY.ATTRIBUTE, attr); mqx_htods(handle->DIR_ENTRY.TIME, PACK_TIME(clk_time)); mqx_htods(handle->DIR_ENTRY.DATE, PACK_DATE(clk_time)); error_code = MFS_Update_entry(drive_ptr, handle); /* ** If the same file is already open, mark it as 'freshly ** truncated' so reads and writes don't clobber any data. */ if ( error_code == MFS_NO_ERROR ) { next_handle = (MFS_HANDLE_PTR) _queue_head(&drive_ptr->HANDLE_LIST); while ( next_handle ) { if ( next_handle->DIR_CLUSTER == dir_cluster && next_handle->DIR_INDEX == dir_index ) { next_handle->CURRENT_CLUSTER = 0; next_handle->PREVIOUS_CLUSTER = 0; } next_handle = (MFS_HANDLE_PTR) _queue_next(&drive_ptr->HANDLE_LIST, (QUEUE_ELEMENT_STRUCT_PTR) next_handle); } } } } /* ** No need to update the disk image if we didn't change anything. */ if ( (mqx_dtohc(handle->DIR_ENTRY.ATTRIBUTE) != attr) && (error_code == MFS_NO_ERROR) ) { mqx_htodc(handle->DIR_ENTRY.ATTRIBUTE, attr); error_code = MFS_Update_entry(drive_ptr, handle); } } else { error_code = MFS_INSUFFICIENT_MEMORY; } } MFS_unlock(drive_ptr,FALSE); if ( error_code == MFS_NO_ERROR && saved_code == MFS_LOST_CHAIN ) { *error_ptr = saved_code; } else { *error_ptr = error_code; } return((void *)handle); }
uint32_t MFS_Read ( MFS_HANDLE_PTR handle, /*[IN] file handle upon which the action is to be taken */ MFS_DRIVE_STRUCT_PTR drive_ptr, uint32_t num_bytes, /*[IN] number of bytes to be read */ char *buffer_address, /*[IN/OUT] bytes are read into this buffer */ _mfs_error_ptr error_ptr /*[IN/OUT] error code is written to this address */ ) { uint32_t location; uint32_t bytes_read; uint32_t bytes_left_in_file; uint32_t copy_size; uint32_t cluster_offset; uint32_t sector_number, sector_index; uint32_t sector_offset; uint32_t whole_sectors; uint32_t cont_sectors; uint32_t proc_sectors; _mfs_error error, temp_error; bool eof_reached; uint32_t file_size; if ( num_bytes == 0 ) { MFS_set_error_and_return(error_ptr,MFS_NO_ERROR,0); } if ( buffer_address == NULL ) { MFS_set_error_and_return(error_ptr,MFS_INVALID_PARAMETER,0); } error = MFS_lock_dos_disk(drive_ptr); if ( error != MFS_NO_ERROR ) { MFS_set_error_and_return(error_ptr,error,0); } if ( handle->ACCESS != MFS_ACCESS_READ_ONLY && handle->ACCESS != MFS_ACCESS_READ_WRITE ) { MFS_unlock(drive_ptr,FALSE); MFS_set_error_and_return(error_ptr,MFS_ACCESS_DENIED,0); } if ( handle->CURRENT_CLUSTER == 0 ) { handle->PREVIOUS_CLUSTER = 0; handle->CURRENT_CLUSTER = clustoh(handle->DIR_ENTRY.HFIRST_CLUSTER, handle->DIR_ENTRY.LFIRST_CLUSTER); } else if ( handle->CURRENT_CLUSTER == CLUSTER_EOF ) { MFS_unlock(drive_ptr,FALSE); MFS_set_error_and_return(error_ptr,MFS_EOF,0); } bytes_read = 0; eof_reached = FALSE; location = handle->LOCATION; /* ** Can't read past file size */ file_size = mqx_dtohl(handle->DIR_ENTRY.FILE_SIZE); if ( location > file_size ) { location = file_size; } bytes_left_in_file = file_size - location; if ( num_bytes > bytes_left_in_file ) { eof_reached = TRUE; num_bytes = bytes_left_in_file; } if ( bytes_left_in_file ) { /* ** Read the number of bytes from the current file ** position to the end of the current cluster */ cluster_offset = OFFSET_WITHIN_CLUSTER(location); sector_index = CLUSTER_OFFSET_TO_SECTOR(cluster_offset); sector_number = CLUSTER_TO_SECTOR(handle->CURRENT_CLUSTER) + sector_index; sector_offset = OFFSET_WITHIN_SECTOR(location); /* Read partial sector if sector_offet is non-zero */ if (sector_offset != 0) { error = MFS_Read_data_sector(drive_ptr, handle, sector_number, TRUE); if ( error == MFS_NO_ERROR ) { /* The requested lenght of data may span the sector to it's end */ copy_size = min(num_bytes, drive_ptr->BPB.SECTOR_SIZE-sector_offset); _mem_copy(&drive_ptr->DATA_SECTOR_PTR[sector_offset], buffer_address, copy_size); bytes_read=copy_size; /* ** Check to see if we need to advance to the next sector, which has ** the side effect of increasing the cluster number if required. */ if ( (sector_offset+bytes_read) >= drive_ptr->BPB.SECTOR_SIZE ) { temp_error = MFS_next_data_sector(drive_ptr, handle, §or_index, §or_number); /* Only an error if we are not done reading */ if ( bytes_read<num_bytes ) { error = temp_error; } } } } /* Check whether the application buffer is properly aligned */ if ((((uint32_t)buffer_address+bytes_read) & drive_ptr->ALIGNMENT_MASK) == 0) { /* Yes, use zero copy approach */ whole_sectors = (num_bytes - bytes_read) >> drive_ptr->SECTOR_POWER; while ((whole_sectors > 0) && (error == MFS_NO_ERROR)) { cont_sectors = drive_ptr->BPB.SECTORS_PER_CLUSTER - sector_index; if (cont_sectors > whole_sectors) cont_sectors = whole_sectors; error = MFS_Read_device_sectors(drive_ptr, sector_number, cont_sectors, MFSCFG_MAX_READ_RETRIES, buffer_address+bytes_read, &proc_sectors); if (proc_sectors > 0) { bytes_read += proc_sectors * drive_ptr->BPB.SECTOR_SIZE; whole_sectors -= proc_sectors; /* Advance to next unprocessed sector */ sector_index += proc_sectors - 1; temp_error = MFS_next_data_sector(drive_ptr, handle, §or_index, §or_number); /* Only an error if we are not done reading */ if ((error==MFS_NO_ERROR) && (bytes_read<num_bytes)) { error = temp_error; } } } } else {