_mfs_error MFS_Flush_caches ( MFS_DRIVE_STRUCT_PTR drive_ptr ) { #if MFSCFG_READ_ONLY return MFS_NO_ERROR; #else _mfs_error error_code, return_code = MFS_NO_ERROR; #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (NULL, drive_ptr)) { return return_code; } #endif return_code = MFS_Flush_directory_sector_buffer(drive_ptr); error_code = MFS_Flush_data_sector_buffer(drive_ptr); if ( return_code == MFS_NO_ERROR ) return_code = error_code; error_code = MFS_Flush_fat_cache(drive_ptr); if ( return_code == MFS_NO_ERROR ) return_code = error_code; return(return_code); #endif }
/*! * \brief Unmounts the filesystem. * * This function brings filesystem on drive to consistent state by flushing * all cached data and releases data structures. * * \param drive_ptr * * \return int Error code. */ int MFS_Unmount_drive_internal( MFS_DRIVE_STRUCT_PTR drive_ptr) { int result = MFS_NO_ERROR; #if !MFSCFG_READ_ONLY if (drive_ptr->FAT_TYPE == MFS_FAT32) { if (!MFS_is_read_only(drive_ptr)) { FILESYSTEM_INFO_DISK_PTR fsinfo_ptr; result = MFS_sector_map(drive_ptr, drive_ptr->FS_INFO, (void **)&fsinfo_ptr, MFS_MAP_MODE_OVERWRITE, 0); if (result == MFS_NO_ERROR) { mqx_htodl(fsinfo_ptr->LEAD_SIG, FSI_LEADSIG); mqx_htodl(fsinfo_ptr->STRUCT_SIG, FSI_STRUCTSIG); mqx_htodl(fsinfo_ptr->FREE_COUNT, drive_ptr->FREE_COUNT); mqx_htodl(fsinfo_ptr->NEXT_FREE, drive_ptr->NEXT_FREE_CLUSTER); mqx_htodl(fsinfo_ptr->TRAIL_SIG, FSI_TRAILSIG); result = MFS_sector_unmap(drive_ptr, drive_ptr->FS_INFO, 1); } } } #endif return result; }
/*FUNCTION*------------------------------------------------------------------- * * Function Name : MFS_Write_back_directory_sector_buffer * Returned Value : MFS error code * Comments : * Write the sector buffer back to the disk. * Assumes the semaphore is already obtained. *END*---------------------------------------------------------------------*/ _mfs_error MFS_Write_back_directory_sector_buffer ( MFS_DRIVE_STRUCT_PTR drive_ptr ) { #if MFSCFG_READ_ONLY return MFS_NO_ERROR; #else _mfs_error error_code = MFS_NO_ERROR; #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (NULL, drive_ptr)) { return error_code; } #endif MFS_LOG(printf("MFS_Write_back_directory_sector_buffer")); drive_ptr->DIR_SECTOR_DIRTY = TRUE; if ( drive_ptr->WRITE_CACHE_POLICY==MFS_WRITE_THROUGH_CACHE ) { error_code = MFS_Flush_directory_sector_buffer(drive_ptr); } return(error_code); #endif }
_mfs_error MFS_Flush_data_sector_buffer ( MFS_DRIVE_STRUCT_PTR drive_ptr /*[IN] the drive on which to operate */ ) { #if MFSCFG_READ_ONLY return MFS_NO_ERROR; #else _mfs_error error_code = MFS_NO_ERROR; #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (NULL, drive_ptr)) { return error_code; } #endif if ( drive_ptr->DATA_SECTOR_DIRTY ) { error_code = MFS_Write_device_sector(drive_ptr,drive_ptr->DATA_SECTOR_NUMBER,drive_ptr->DATA_SECTOR_PTR); if ( error_code == MFS_NO_ERROR ) { drive_ptr->DATA_SECTOR_DIRTY=FALSE; } } return error_code; #endif }
/*FUNCTION*------------------------------------------------------------------- * * Function Name : MFS_Flush_directory_sector_buffer * Returned Value : MFS error code * Comments : * Write the sector buffer back to the disk. * Assumes the semaphore is already obtained. *END*---------------------------------------------------------------------*/ _mfs_error MFS_Flush_directory_sector_buffer ( MFS_DRIVE_STRUCT_PTR drive_ptr ) { #if MFSCFG_READ_ONLY return MFS_NO_ERROR; #else _mfs_error error_code= MFS_NO_ERROR; #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (NULL, drive_ptr)) { return error_code; } #endif if ( drive_ptr->DIR_SECTOR_DIRTY ) { error_code = MFS_Write_device_sector(drive_ptr,drive_ptr->DIR_SECTOR_NUMBER,drive_ptr->DIR_SECTOR_PTR); drive_ptr->DIR_SECTOR_DIRTY = FALSE; } return(error_code); #endif }
_mfs_error MFS_Clear_cluster ( MFS_DRIVE_STRUCT_PTR drive_ptr, /*[IN] the drive on which to operate */ uint_32 cluster /*[IN] the # of the cluster to clear*/ ) { uint_32 sector,i; _mfs_error error_code; #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (NULL, drive_ptr)) { return MFS_DISK_IS_WRITE_PROTECTED; } #endif error_code = MFS_Flush_directory_sector_buffer(drive_ptr); sector = CLUSTER_TO_SECTOR(cluster); _mem_zero(drive_ptr->DIR_SECTOR_PTR, drive_ptr->BPB.SECTOR_SIZE); for ( i = 0; ((i<drive_ptr->BPB.SECTORS_PER_CLUSTER) && (error_code==MFS_NO_ERROR));i++ ) { error_code = MFS_Write_device_sector(drive_ptr,sector+i,drive_ptr->DIR_SECTOR_PTR); } drive_ptr->DIR_SECTOR_NUMBER = sector; return(error_code); }
_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); }
void MFS_Decrement_free_clusters(MFS_DRIVE_STRUCT_PTR drive_ptr) { #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (NULL, drive_ptr)) { return; } #endif if ( drive_ptr->FREE_COUNT != FSI_UNKNOWN ) { drive_ptr->FREE_COUNT--; } }
_mfs_error MFS_Flush_fat_cache ( MFS_DRIVE_STRUCT_PTR drive_ptr /*[IN] the drive on which to operate */ ) { #if MFSCFG_READ_ONLY return MFS_NO_ERROR; #else _mfs_error error_code; uint_32 fat_size,fat,i; error_code = MFS_NO_ERROR; #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (NULL, drive_ptr)) { return error_code; } #endif if ( drive_ptr->FAT_CACHE_DIRTY ) { if ( drive_ptr->FAT_TYPE == MFS_FAT32 ) { fat_size = drive_ptr->BPB32.FAT_SIZE; } else { fat_size = drive_ptr->BPB.SECTORS_PER_FAT; } /* Backup all copies of fat */ for ( fat=0; (fat<drive_ptr->BPB.NUMBER_OF_FAT) && (error_code==MFS_NO_ERROR); fat++ ) { for ( i=0; (i<drive_ptr->FAT_CACHE_SIZE) && (error_code==MFS_NO_ERROR); i++ ) { error_code = MFS_Write_device_sector(drive_ptr, drive_ptr->FAT_START_SECTOR + drive_ptr->FAT_CACHE_START + i + (fat * fat_size), (pointer) &drive_ptr->FAT_CACHE_PTR[drive_ptr->BPB.SECTOR_SIZE*i]); } } if ( error_code == MFS_NO_ERROR ) { drive_ptr->FAT_CACHE_DIRTY = FALSE; } } return(error_code); #endif }
uint_32 MFS_Find_unused_cluster_from ( MFS_DRIVE_STRUCT_PTR drive_ptr, /*[IN] the drive on which to operate */ uint_32 cluster_number /*[IN] first cluster number to search */ ) { uint_32 max_clusters,cluster; _mfs_error error_code; uint_32 cluster_status; #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (NULL, drive_ptr)) { return CLUSTER_INVALID; } #endif max_clusters = drive_ptr->LAST_CLUSTER; for ( cluster = cluster_number; cluster <= max_clusters; cluster++ ) { error_code = MFS_get_cluster_from_fat(drive_ptr,cluster,&cluster_status); if ( error_code != MFS_NO_ERROR ) { return(CLUSTER_INVALID); } else if ( cluster_status == CLUSTER_UNUSED ) { drive_ptr->NEXT_FREE_CLUSTER = cluster; return(cluster); } } for ( cluster = CLUSTER_MIN_GOOD; cluster < cluster_number; cluster++ ) { error_code = MFS_get_cluster_from_fat(drive_ptr,cluster, &cluster_status); if ( error_code != MFS_NO_ERROR ) { return(CLUSTER_INVALID); } else if ( cluster_status == CLUSTER_UNUSED ) { drive_ptr->NEXT_FREE_CLUSTER = cluster; return(cluster); } } return(CLUSTER_INVALID); }
/*! * \brief * * Verifies that the drive is mounted and possibly checks other preconditions. * The function assumes that the drive is locked. * * \param drive_ptr * \param mode * * \return _mfs_error */ _mfs_error MFS_enter( MFS_DRIVE_STRUCT_PTR drive_ptr, int mode) { if (!drive_ptr->DOS_DISK) { return MFS_NOT_A_DOS_DISK; } if ((mode & MFS_ENTER_READWRITE) && MFS_is_read_only(drive_ptr)) { return MFS_DISK_IS_WRITE_PROTECTED; } return MFS_NO_ERROR; }
_mfs_error MFS_Update_entry ( MFS_DRIVE_STRUCT_PTR drive_ptr, /*[IN] the drive on which to operate */ MFS_HANDLE_PTR handle /*[IN] Update this file */ ) { uint_32 dir_index; uint_32 dir_cluster; _mfs_error error_code = MFS_NO_ERROR; MFS_DIR_ENTRY_PTR dir_entry_ptr; uint_32 prev_cluster; #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (NULL, drive_ptr)) { return MFS_DISK_IS_WRITE_PROTECTED; } #endif if ( handle == NULL ) { error_code = MFS_INVALID_HANDLE; } else { dir_cluster = handle->DIR_CLUSTER; dir_index = handle->DIR_INDEX; 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 ) { error_code = MFS_FILE_NOT_FOUND; } else { _mem_copy(&handle->DIR_ENTRY, dir_entry_ptr, sizeof(MFS_DIR_ENTRY)); drive_ptr->DIR_SECTOR_DIRTY = TRUE; } } return(error_code); }
_mfs_error MFS_Invalidate_data_sector ( MFS_DRIVE_STRUCT_PTR drive_ptr /*[IN] the drive on which to operate */ ) { #if MFSCFG_READ_ONLY return MFS_NO_ERROR; #else #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (NULL, drive_ptr)) { return MFS_NO_ERROR; } #endif drive_ptr->DATA_SECTOR_NUMBER = MAX_UINT_32; drive_ptr->DATA_SECTOR_DIRTY=FALSE; return MFS_NO_ERROR; #endif }
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; }
_mfs_error MFS_Write_back_fat ( MFS_DRIVE_STRUCT_PTR drive_ptr ) { #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (NULL, drive_ptr)) { return MFS_DISK_IS_WRITE_PROTECTED; } #endif if ( drive_ptr->FAT_CACHE_POLICY == MFS_WRITE_THROUGH_CACHE ) { return( MFS_Flush_fat_cache(drive_ptr) ); } else { return( MFS_NO_ERROR ); } }
int_32 MFS_Close_Device ( MQX_FILE_PTR fd_ptr /* [IN] the MFS file handle for the device being closed */ ) { MFS_DRIVE_STRUCT_PTR drive_ptr; FILESYSTEM_INFO_DISK_PTR fsinfo_ptr; int_32 result = MFS_NO_ERROR; #if !MFSCFG_READ_ONLY #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (fd_ptr, NULL)) { result = MFS_DISK_IS_WRITE_PROTECTED; } #endif if (result != MFS_DISK_IS_WRITE_PROTECTED) { result = _io_ioctl(fd_ptr, IO_IOCTL_FLUSH_OUTPUT, NULL); } #endif MFS_lock(fd_ptr, &drive_ptr); #if !MFSCFG_READ_ONLY if (result != MFS_DISK_IS_WRITE_PROTECTED) { MFS_Flush_caches(drive_ptr); } #endif if ( _queue_is_empty(&drive_ptr->HANDLE_LIST) ) { if ( drive_ptr->FAT_TYPE == MFS_FAT32 ) { #if !MFSCFG_READ_ONLY if (result != MFS_DISK_IS_WRITE_PROTECTED) { fsinfo_ptr = (FILESYSTEM_INFO_DISK_PTR)drive_ptr->DATA_SECTOR_PTR; if ( fsinfo_ptr != NULL ) { htodl(fsinfo_ptr->LEAD_SIG, FSI_LEADSIG); htodl(fsinfo_ptr->STRUCT_SIG, FSI_STRUCTSIG); htodl(fsinfo_ptr->FREE_COUNT, drive_ptr->FREE_COUNT); htodl(fsinfo_ptr->NEXT_FREE, drive_ptr->NEXT_FREE_CLUSTER); htodl(fsinfo_ptr->TRAIL_SIG, FSI_TRAILSIG); MFS_Write_device_sector(drive_ptr, FSINFO_SECTOR, (char_ptr)fsinfo_ptr); } } #endif } MFS_free_drive_data(drive_ptr, TRUE); drive_ptr->MFS_FILE_PTR = NULL; result = MFS_NO_ERROR; } else { /* liutest add for get unclose handle */ MFS_HANDLE_PTR next_handle; next_handle = (MFS_HANDLE_PTR) _queue_head(&drive_ptr->HANDLE_LIST); while ( next_handle ) { printf("unclose handle 0x%X\n",(uint_32)next_handle); next_handle = (MFS_HANDLE_PTR) _queue_next(&drive_ptr->HANDLE_LIST, (QUEUE_ELEMENT_STRUCT_PTR) next_handle); } result = MFS_SHARING_VIOLATION; /* MFS_free_drive_data(drive_ptr, TRUE); drive_ptr->MFS_FILE_PTR = NULL; result = MFS_NO_ERROR;*/ } MFS_unlock(drive_ptr,FALSE); return result; }
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); }
_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); }
/*FUNCTION*------------------------------------------------------------------- * * Function Name : MFS_Write_device_sectors * Returned Value : error_code * Comments : * Reads or writes consecutive sectors. *END*---------------------------------------------------------------------*/ _mfs_error MFS_Write_device_sectors ( MFS_DRIVE_STRUCT_PTR drive_ptr, uint_32 sector_number, /*[IN] first sector to read/write from/to file system medium */ uint_32 sector_count, /*[IN] number of sectors to read/write from/to file system medium */ uint_32 max_retries, /*[IN] number of retries of the same low level operation if it fails */ char_ptr buffer_ptr, /*[IN/OUT] address of where data is to be stored/written */ uint_32_ptr processed /*[OUT] number of sector successfully processed */ ) { uint_32 attempts; int_32 num, expect_num, seek_loc, shifter; char_ptr data_ptr; _mfs_error error; #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (NULL, drive_ptr)) { return MFS_DISK_IS_WRITE_PROTECTED; } #endif error = MFS_NO_ERROR; MFS_LOG(printf("MFS_Write_device_sector %d\n", sector_number)); if ( sector_number > drive_ptr->BPB.MEGA_SECTORS ) { return(MFS_SECTOR_NOT_FOUND); } if ( drive_ptr->BLOCK_MODE ) { shifter = 0; seek_loc = sector_number; expect_num = sector_count; } else { shifter = drive_ptr->SECTOR_POWER; seek_loc = sector_number << shifter; expect_num = sector_count << shifter; } fseek(drive_ptr->DEV_FILE_PTR, seek_loc, IO_SEEK_SET); data_ptr = buffer_ptr; attempts = 0; while ( expect_num > 0 && attempts <= max_retries) { num = write(drive_ptr->DEV_FILE_PTR, data_ptr, expect_num); if ( num == IO_ERROR ) { error = IO_ERROR_WRITE; break; } if ( num > 0 ) { expect_num -= num; data_ptr += num << (drive_ptr->SECTOR_POWER - shifter); attempts = 0; /* there is a progress, reset attempts counter */ } attempts++; } if ( expect_num > 0 ) { error = drive_ptr->DEV_FILE_PTR->ERROR; } else if (drive_ptr->READBACK_SECTOR_PTR) { fseek(drive_ptr->DEV_FILE_PTR, seek_loc, IO_SEEK_SET); data_ptr = buffer_ptr; expect_num = sector_count << shifter; while ( expect_num > 0 ) { num = read(drive_ptr->DEV_FILE_PTR, drive_ptr->READBACK_SECTOR_PTR, 1<<shifter); if ( num != (1<<shifter) ) { error = drive_ptr->DEV_FILE_PTR->ERROR; break; } if ( memcmp(data_ptr, drive_ptr->READBACK_SECTOR_PTR, drive_ptr->BPB.SECTOR_SIZE) != 0 ) { error = IO_ERROR_WRITE; break; } expect_num -= num; data_ptr += num << (drive_ptr->SECTOR_POWER - shifter); } } switch ( error ) { case IO_ERROR_WRITE_PROTECTED: error = MFS_DISK_IS_WRITE_PROTECTED; break; case IO_ERROR_WRITE: error = MFS_WRITE_FAULT; break; case IO_ERROR_WRITE_ACCESS: error = MFS_SECTOR_NOT_FOUND; break; case IO_ERROR_READ: error = MFS_READ_FAULT; break; case IO_ERROR_READ_ACCESS: error = MFS_SECTOR_NOT_FOUND; break; case MFS_NO_ERROR: /* Ensure that error code is always set if less than requested data was written */ if ( expect_num > 0 ) error = MFS_WRITE_FAULT; break; default: break; } if (processed) *processed = ((sector_count<<shifter) - expect_num) >> shifter; return error; }
_mfs_error MFS_Extend_chain ( MFS_DRIVE_STRUCT_PTR drive_ptr, /*[IN] the drive on which to operate */ uint_32 cluster_number, /*[IN] number of a cluster within the chain */ uint_32 num_clusters, /*[IN] number of clusters to append to chain */ uint_32_ptr added_cluster /* [IN] pointer to the place where we should put the # of the first new cluster. */ ) { uint_32 next_cluster; _mfs_error error_code; boolean extended; #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (NULL, drive_ptr)) { return MFS_DISK_IS_WRITE_PROTECTED; } #endif extended = FALSE; error_code = MFS_NO_ERROR; if ( cluster_number < CLUSTER_MIN_GOOD || cluster_number > drive_ptr->LAST_CLUSTER ) { error_code = MFS_INVALID_CLUSTER_NUMBER; } else if ( num_clusters ) { /* ** Find the end of the chain */ next_cluster = cluster_number; do { cluster_number = next_cluster; error_code = MFS_get_cluster_from_fat(drive_ptr,next_cluster, &next_cluster); if ( error_code != MFS_NO_ERROR ) { return error_code; } else if ( (next_cluster > drive_ptr->LAST_CLUSTER || next_cluster < CLUSTER_MIN_GOOD) && next_cluster != CLUSTER_EOF ) { return(MFS_LOST_CHAIN); } } while ( next_cluster != CLUSTER_EOF ); /* ** Find a free cluster */ next_cluster = MFS_Find_unused_cluster_from(drive_ptr, cluster_number+1); /* ** Check to see if the disk is not full. */ if ( next_cluster == CLUSTER_INVALID ) { return MFS_DISK_FULL; } /* ** Link the free cluster to the chain, at the end. */ *added_cluster = next_cluster; error_code = MFS_Put_fat(drive_ptr,cluster_number, next_cluster); extended = TRUE; while ( --num_clusters && !error_code ) { /* ** Find a free cluster */ cluster_number = next_cluster; next_cluster = MFS_Find_unused_cluster_from(drive_ptr, cluster_number+1); /* ** Check to see if the disk is not full. */ if ( next_cluster == CLUSTER_INVALID ) { error_code = MFS_Put_fat(drive_ptr,cluster_number, CLUSTER_EOF); return MFS_DISK_FULL; } else { /* ** Link the free cluster to the chain, at the end. */ error_code = MFS_Put_fat(drive_ptr,cluster_number, next_cluster); } } if ( extended && !error_code ) { error_code = MFS_Put_fat(drive_ptr,next_cluster, CLUSTER_EOF); } } return(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_Add_cluster_to_chain ( MFS_DRIVE_STRUCT_PTR drive_ptr, /*[IN] the drive on which to operate */ uint_32 cluster_number, /*[IN] number of a cluster within the chain */ uint_32_ptr added_cluster /*[IN] pointer to the place where we should put the # of the new cluster. */ ) { uint_32 next_cluster,free_cluster; _mfs_error error_code; #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (NULL, drive_ptr)) { return MFS_DISK_IS_WRITE_PROTECTED; } #endif if ( cluster_number < CLUSTER_MIN_GOOD || cluster_number > drive_ptr->LAST_CLUSTER ) { error_code = MFS_INVALID_CLUSTER_NUMBER; } else { free_cluster = MFS_Find_unused_cluster_from(drive_ptr, drive_ptr->NEXT_FREE_CLUSTER); /* ** Check to see if the disk is not full. */ if ( free_cluster == CLUSTER_INVALID ) { error_code = MFS_DISK_FULL; } else { /* ** Find the end of the chain */ next_cluster = cluster_number; do { cluster_number = next_cluster; error_code = MFS_get_cluster_from_fat(drive_ptr,next_cluster, &next_cluster); if ( error_code != MFS_NO_ERROR ) { break; } else if ( next_cluster > drive_ptr->LAST_CLUSTER && next_cluster != CLUSTER_EOF ) { error_code = MFS_BAD_DISK_UNIT; break; } } while ( next_cluster != CLUSTER_EOF ); /* ** Link the free cluster to the chain, at the end. */ if ( error_code == MFS_NO_ERROR ) { error_code = MFS_Put_fat(drive_ptr,cluster_number, free_cluster); if ( error_code ) { return(error_code); } error_code = MFS_Put_fat(drive_ptr,free_cluster, CLUSTER_EOF); if ( error_code ) { return(error_code); } *added_cluster = free_cluster; } } } return(error_code); }
_mfs_error MFS_Release_chain ( MFS_DRIVE_STRUCT_PTR drive_ptr, /*[IN] the drive on which to operate */ uint_32 cluster_number /*[IN] first cluster number to release */ ) { uint_32 next_cluster,first_sector_in_cluster,last_sector_in_cluster; _mfs_error error_code; #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (NULL, drive_ptr)) { return MFS_DISK_IS_WRITE_PROTECTED; } #endif if ( (cluster_number >= CLUSTER_MIN_GOOD) && (cluster_number <= drive_ptr->LAST_CLUSTER) ) { do { error_code = MFS_get_cluster_from_fat(drive_ptr,cluster_number,&next_cluster); if ( error_code != MFS_NO_ERROR ) { break; } else if ( ((next_cluster > drive_ptr->LAST_CLUSTER) || (next_cluster < CLUSTER_MIN_GOOD)) && (next_cluster != CLUSTER_EOF) ) { error_code = MFS_LOST_CHAIN; break; } first_sector_in_cluster = CLUSTER_TO_SECTOR(cluster_number); last_sector_in_cluster = first_sector_in_cluster+ drive_ptr->BPB.SECTORS_PER_CLUSTER -1; // Check to see if the currently cached data sector is being deleted. if ( (drive_ptr->DATA_SECTOR_NUMBER >= first_sector_in_cluster) && (drive_ptr->DATA_SECTOR_NUMBER <= last_sector_in_cluster) ) { error_code = MFS_Invalidate_data_sector(drive_ptr); if ( error_code != MFS_NO_ERROR ) { return error_code; } } error_code = MFS_Put_fat(drive_ptr,cluster_number, CLUSTER_UNUSED); if ( error_code ) { break; } cluster_number = next_cluster; } while ( cluster_number != CLUSTER_EOF ); error_code = MFS_Write_back_fat(drive_ptr); } else { error_code = MFS_NO_ERROR; } 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_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_DIR_ENTRY_PTR MFS_Create_directory_entry ( MFS_DRIVE_STRUCT_PTR drive_ptr, /*[IN] the drive on which to operate */ char_ptr filename_ptr, /*[IN] pointer to the file's name */ char attribute, /*[IN] attribute to be assigned to the file */ uint_32_ptr dir_cluster_ptr, /*[IN/OUT] indicates cluster in which the entry was put.*/ uint_32_ptr dir_index_ptr, /*[IN/OUT] index of the location of new file within the directory */ uint_32_ptr error_ptr /*[IN/OUT] error_return_address */ ) { MFS_DIR_ENTRY_PTR dir_entry_ptr, dir_entry_ptr1; MFS_DIR_ENTRY_PTR temp_entry_ptr; TIME_STRUCT time; DATE_STRUCT clk_time; uint_32 dir_index, saved_index, temp_index; uint_32 entry_cluster, saved_cluster, temp_cluster; uint_32 needed_entries, i; int_32 length; boolean found_all = FALSE; char temp_name[SFILENAME_SIZE+1], short_name[SFILENAME_SIZE+1]; uchar checksum = 0; uint_32 prev_cluster= CLUSTER_INVALID, saved_prev_cluster, temp_prev_cluster; dir_entry_ptr = NULL; entry_cluster = *dir_cluster_ptr; dir_index = 0; /* ** Check for duplicate file */ if ( filename_ptr == NULL ) { *error_ptr = MFS_INVALID_PARAMETER; } else if ( *filename_ptr == '\0' ) { *error_ptr = MFS_FILE_NOT_FOUND; } #if MFSCFG_READ_ONLY_CHECK else if (MFS_is_read_only (NULL, drive_ptr)) { *error_ptr = MFS_DISK_IS_WRITE_PROTECTED; } #endif else if ( (dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, filename_ptr, &entry_cluster, &dir_index, &prev_cluster, MFS_ATTR_ANY, error_ptr)) != NULL ) { *error_ptr = MFS_FILE_EXISTS; } else { /* ** Search for an empty slot */ dir_index = 0; dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &entry_cluster, &dir_index, &prev_cluster, attribute, error_ptr); if ( MFS_Dirname_valid(filename_ptr) ) { found_all = TRUE; } if ( dir_entry_ptr == NULL && !*error_ptr ) { found_all = TRUE; } /* ** Save it now because we might not go into the while loop ** If we don't go into while, we lose original values when these ** variables are restored after the while loop */ saved_cluster = entry_cluster; saved_index = dir_index; while ( !found_all ) { /* Calculate the amount of extra entries needed for LFN's */ saved_cluster = entry_cluster; saved_index = dir_index; for ( needed_entries = (strlen(filename_ptr) + 12) / 13; needed_entries >= 1 && !found_all; needed_entries-- ) { *error_ptr = MFS_Increment_dir_index(drive_ptr, &entry_cluster, &dir_index, NULL); if ( entry_cluster == CLUSTER_EOF && !*error_ptr ) { /* This means the LFN will span a cluster. */ found_all = TRUE; break; } temp_index = dir_index; temp_cluster = entry_cluster; temp_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &entry_cluster, &dir_index, &prev_cluster, MFS_ATTR_ANY,error_ptr); if ( *error_ptr ) { return NULL; } if ( !temp_entry_ptr ) { found_all = TRUE; dir_entry_ptr = NULL; break; } else if ( dir_index == temp_index && temp_cluster == entry_cluster ) { continue; } else { break; } } if ( needed_entries == 0 ) { found_all = TRUE; } if ( found_all ) { dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &saved_cluster, &saved_index, &saved_prev_cluster, MFS_ATTR_ANY,error_ptr); } } entry_cluster = saved_cluster; dir_index = saved_index; if ( dir_entry_ptr == NULL && !*error_ptr ) { /* ** Empty spot not found... get a new cluster and use the first entry. */ dir_index = 0; if ( entry_cluster == 0 ) { *error_ptr = MFS_ROOT_DIR_FULL; return(NULL); } else { *error_ptr = MFS_Add_cluster_to_chain(drive_ptr, entry_cluster, &entry_cluster); if ( *error_ptr == MFS_NO_ERROR ) { *error_ptr = MFS_Clear_cluster(drive_ptr, entry_cluster); if ( *error_ptr ) { return(NULL); } dir_entry_ptr = (pointer) drive_ptr->DIR_SECTOR_PTR; *error_ptr = MFS_Write_back_fat(drive_ptr); if ( *error_ptr ) { return(NULL); } } } } } if ( *error_ptr == MFS_NO_ERROR ) { /* At this point we have one of the following cases ** ** 1. We have a normal 8.3 filename and an empty slot for it ** 2. We have a LFN, and a slot which has enough consecutive free slots ** to store the LFN, followed by the actual entry */ /* If the file is a normal 8.3 file */ if ( MFS_Dirname_valid(filename_ptr) ) { _mem_zero(dir_entry_ptr, sizeof (MFS_DIR_ENTRY)); htodc(dir_entry_ptr->ATTRIBUTE, attribute); MFS_Expand_dotfile(filename_ptr, dir_entry_ptr->NAME); _time_get(&time); _time_to_date(&time, &clk_time); NORMALIZE_DATE(&clk_time); htods(dir_entry_ptr->TIME, PACK_TIME(clk_time)); htods(dir_entry_ptr->DATE, PACK_DATE(clk_time)); drive_ptr->DIR_SECTOR_DIRTY = TRUE; } else { /* Case where the file is a LFN */ length = strlen(filename_ptr); /* Get the 8.3 name and calculate the checksum */ temp_index = 0; temp_cluster = *dir_cluster_ptr; *error_ptr = MFS_lfn_to_sfn(filename_ptr, temp_name); if ( !*error_ptr ) { do { dir_entry_ptr1 = MFS_Find_directory_entry(drive_ptr, temp_name, &temp_cluster, &temp_index, &temp_prev_cluster, MFS_ATTR_ANY, error_ptr); if ( !*error_ptr && dir_entry_ptr1 != NULL ) { MFS_increment_lfn(temp_name); temp_index = 0; } } while ( !*error_ptr && dir_entry_ptr1 != NULL ); dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &entry_cluster, &dir_index, &prev_cluster, attribute, error_ptr); /* ** The memory should be cleared after finding the directory entry. */ _mem_zero(dir_entry_ptr, sizeof (MFS_DIR_ENTRY)); /* Setup the final slot */ ((MFS_LNAME_ENTRY_PTR) dir_entry_ptr)->ID |= MFS_LFN_END; drive_ptr->DIR_SECTOR_DIRTY = TRUE; MFS_Expand_dotfile(temp_name,short_name); checksum = MFS_lfn_checksum(short_name); } while ( length && !*error_ptr ) { i = length - ((length -1) % 13 + 1); *error_ptr = MFS_lfn_name_to_entry(filename_ptr + i, (MFS_LNAME_ENTRY_PTR) dir_entry_ptr); /* Set the entry number, the checksum value and the attribute */ ((MFS_LNAME_ENTRY_PTR) dir_entry_ptr)->ID |= (length + 12) / 13; ((MFS_LNAME_ENTRY_PTR) dir_entry_ptr)->ALIAS_CHECKSUM= checksum; ((MFS_LNAME_ENTRY_PTR) dir_entry_ptr)->ATTR = MFS_ATTR_LFN; drive_ptr->DIR_SECTOR_DIRTY = TRUE; length -= (length - i); if ( length < 0 ) { length = 0; } if ( length && !*error_ptr ) { dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &entry_cluster, &dir_index, &prev_cluster, attribute, error_ptr); if ( dir_entry_ptr == NULL && !*error_ptr ) { /* No empty spots... We need to get a new cluster */ dir_index = 0; if ( entry_cluster == 0 ) { *error_ptr = MFS_ROOT_DIR_FULL; return(NULL); } else { *error_ptr = MFS_Add_cluster_to_chain( drive_ptr, entry_cluster, &entry_cluster); if ( *error_ptr == MFS_NO_ERROR ) { *error_ptr = MFS_Clear_cluster(drive_ptr, entry_cluster); if ( *error_ptr ) { return(NULL); } dir_entry_ptr = (pointer) drive_ptr->DIR_SECTOR_PTR; *error_ptr = MFS_Write_back_fat(drive_ptr); if ( *error_ptr ) { return(NULL); } } } } _mem_zero(dir_entry_ptr, sizeof (MFS_DIR_ENTRY)); drive_ptr->DIR_SECTOR_DIRTY = TRUE; } } /* LFN is written, so write the actual entry */ if ( !*error_ptr ) { dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &entry_cluster, &dir_index, &prev_cluster, attribute, error_ptr); if ( dir_entry_ptr == NULL && !*error_ptr ) { dir_index = 0; if ( entry_cluster == 0 ) { *error_ptr = MFS_ROOT_DIR_FULL; return(NULL); } else { *error_ptr = MFS_Add_cluster_to_chain( drive_ptr, entry_cluster, &entry_cluster); if ( *error_ptr == MFS_NO_ERROR ) { *error_ptr = MFS_Clear_cluster(drive_ptr, entry_cluster); if ( *error_ptr ) { return(NULL); } dir_entry_ptr = (pointer) drive_ptr->DIR_SECTOR_PTR; *error_ptr = MFS_Write_back_fat(drive_ptr); if ( *error_ptr ) { return(NULL); } } } } _mem_zero(dir_entry_ptr, sizeof (MFS_DIR_ENTRY)); htodc(dir_entry_ptr->ATTRIBUTE, attribute); MFS_Expand_dotfile(temp_name, dir_entry_ptr->NAME); _time_get(&time); _time_to_date(&time, &clk_time); NORMALIZE_DATE(&clk_time); htods(dir_entry_ptr->TIME, PACK_TIME(clk_time)); htods(dir_entry_ptr->DATE, PACK_DATE(clk_time)); drive_ptr->DIR_SECTOR_DIRTY = TRUE; } } if ( *error_ptr ) { return(NULL); } } *dir_cluster_ptr = entry_cluster; *dir_index_ptr = dir_index; return(dir_entry_ptr); }
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_DIR_ENTRY_PTR MFS_Create_entry_slave ( MFS_DRIVE_STRUCT_PTR drive_ptr, /*[IN] the drive on which to operate */ uchar attr, /*[IN] attribute to be given to the new file */ char_ptr pathname, /*[IN] directory and file name to be given to the new file */ uint_32_ptr cluster_ptr, /*[OUT] cluster # in the directory where the entry was created */ uint_32_ptr index_ptr, /*[OUT] index # in the directory where the entry was created*/ _mfs_error_ptr error_ptr, /*[IN/OUT] error code is written to this address */ boolean overwrite /*[IN] if TRUE, we will overwrite an existing entry w/the same name */ ) { MFS_DIR_ENTRY_PTR dir_entry_ptr; char_ptr temp_dirname; char_ptr temp_filename; uchar at; uint_32 dir_cluster; uint_32 dir_index; uint_32 vol_cluster, vol_index; _mfs_error error_code; uint_32 prev_cluster; #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (NULL, drive_ptr)) { if ( error_ptr ) { *error_ptr = MFS_DISK_IS_WRITE_PROTECTED; } return NULL; } #endif dir_index = 0; dir_cluster = drive_ptr->CUR_DIR_CLUSTER; dir_entry_ptr = NULL; error_code = MFS_alloc_2paths(&temp_dirname,&temp_filename); if ( error_code ) { return( NULL ); } error_code = MFS_Parse_pathname(temp_dirname, temp_filename, pathname); if ( error_code == MFS_NO_ERROR ) { dir_cluster = MFS_Find_directory(drive_ptr, temp_dirname, dir_cluster); if ( dir_cluster == CLUSTER_INVALID ) { error_code = MFS_PATH_NOT_FOUND; } else { if ( MFS_is_valid_lfn(temp_filename) ) { if ( attr & MFS_ATTR_VOLUME_NAME ) { /* ** If creating a volume label, it must be in the root ** directory. */ if ( dir_cluster == 0 ) { vol_cluster = 0; 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 ) { error_code = MFS_ALREADY_ASSIGNED; } } else { error_code = MFS_ACCESS_DENIED; } } if ( error_code == MFS_NO_ERROR ) { dir_entry_ptr = MFS_Create_directory_entry(drive_ptr, temp_filename, attr, &dir_cluster, &dir_index, &error_code); /* if dir_entry_ptr == NULL ** we couldn't create a new entry. ** if not NULL, it may be a brand new entry (MFS_NO_ERROR) or ** an old one (MFS_FILE_EXISTS) */ if ( dir_entry_ptr != NULL ) { at = dtohc(dir_entry_ptr->ATTRIBUTE); if ( (error_code != MFS_NO_ERROR) && (overwrite == FALSE) ) { dir_entry_ptr = NULL; } else if ( (error_code == MFS_FILE_EXISTS) && ((at & MFS_ATTR_DIR_NAME) != (attr & MFS_ATTR_DIR_NAME)) || ((at & MFS_ATTR_VOLUME_NAME) != (attr & MFS_ATTR_VOLUME_NAME)) ) { error_code = MFS_WRITE_FAULT; dir_entry_ptr = NULL; } else if ( at & MFS_ATTR_READ_ONLY && error_code != MFS_NO_ERROR ) { /* ** If not freshly created */ error_code = MFS_ACCESS_DENIED; dir_entry_ptr = NULL; } } *cluster_ptr = dir_cluster; *index_ptr = dir_index; } } else { error_code = MFS_INVALID_PARAMETER; dir_entry_ptr = NULL; } } } if ( error_ptr ) { *error_ptr = error_code; } MFS_free_path(temp_filename); MFS_free_path(temp_dirname); return(dir_entry_ptr); }
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); }
/*FUNCTION*------------------------------------------------------------------- * * Function Name : MFS_Write_device_sector * Returned Value : error_code * Comments : * Reads or writes consecutive clusters. *END*---------------------------------------------------------------------*/ _mfs_error MFS_Write_device_sector ( MFS_DRIVE_STRUCT_PTR drive_ptr, uint_32 sector_number, /*[IN] sector number to read/write from/to file system medium */ char_ptr buffer_ptr /*[IN/OUT] address of where data is to be stored/written */ ) { uint_32 new_cluster_number, next_cluster, bad_cluster_number; uint_32 i; uint_32 retries, attempts; uint_32 new_sector_number, no_of_sectors; char_ptr temp_buffer_ptr; int_32 num, expect_num, shifter, seek_loc, tmp; _mfs_error error; #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (NULL, drive_ptr)) { return MFS_DISK_IS_WRITE_PROTECTED; } #endif error = MFS_NO_ERROR; MFS_LOG(printf("MFS_Write_device_sector %d\n", sector_number)); if ( sector_number > drive_ptr->BPB.MEGA_SECTORS ) { return(MFS_SECTOR_NOT_FOUND); } attempts = 0; /* Lock device */ ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_LOCK, &drive_ptr->DRV_NUM); if ( drive_ptr->BLOCK_MODE ) { shifter = 0; seek_loc = sector_number; expect_num = 1; } else { shifter = drive_ptr->SECTOR_POWER; seek_loc = sector_number << shifter; expect_num = 1 << shifter; } MFS_device_write_internal(drive_ptr, seek_loc, buffer_ptr, &expect_num, &buffer_ptr, shifter); if ( expect_num > 0 ) { error = drive_ptr->DEV_FILE_PTR->ERROR; #if MFSCFG_MAX_CLUSTER_REMAP_ATTEMPTS /* ** Check to see if the write failed due to a bad sector. If so, ** rewrite cluster by cluster until we find bad cluster, then move ** it. */ temp_buffer_ptr = buffer_ptr; if ( drive_ptr->BLOCK_MODE ) { expect_num = drive_ptr->BPB.SECTORS_PER_CLUSTER; } else { expect_num = drive_ptr->CLUSTER_SIZE_BYTES; } tmp = expect_num; for ( i = 0; i < no_of_clusters; i++ ) { MFS_device_write_internal(drive_ptr, seek_loc, temp_buffer_ptr, &expect_num, &buffer_ptr, shifter); if ( expect_num > 0 ) { error_code = drive_ptr->DEV_FILE_PTR->ERROR; ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_UNLOCK, &drive_ptr->DRV_NUM); bad_cluster_number = cluster_number + i; error_code = MFS_get_cluster_from_fat(drive_ptr, bad_cluster_number, &next_cluster); if ( error_code != MFS_NO_ERROR ) { /* ** This is done so that the unlock at end of function ** works properly */ ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_LOCK, &drive_ptr->DRV_NUM); break; } retries = MFSCFG_MAX_CLUSTER_REMAP_ATTEMPTS; while ( (error_code != MFS_NO_ERROR) && retries-- ) { /* ** Mark old cluster BAD */ error_code = MFS_Put_fat(drive_ptr, bad_cluster_number, CLUSTER_BAD); if ( error_code ) { break; } /* ** Find available fat, update old FAT as invalid, ** update new fat, and write new cluster. */ new_cluster_number = MFS_Find_unused_cluster_from(drive_ptr, bad_cluster_number); if ( new_cluster_number == CLUSTER_INVALID ) { /* ** No more clusters */ return MFS_DISK_FULL; } new_sector_number = drive_ptr->DATA_START_SECTOR + ((uint_32)(new_cluster_number - CLUSTER_MIN_GOOD)) * drive_ptr->BPB.SECTORS_PER_CLUSTER; ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_LOCK, &drive_ptr->DRV_NUM); expect_num = tmp; MFS_device_write_internal(drive_ptr, new_sector_number << shifter, temp_buffer_ptr, &expect_num, &buffer_ptr, shifter); if ( expect_num > 0 ) { error_code = drive_ptr->DEV_FILE_PTR->ERROR; } ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_UNLOCK, &(drive_ptr->DRV_NUM)); bad_cluster_number = new_cluster_number; } if ( error_code != MFS_NO_ERROR ) { return MFS_WRITE_FAULT; } /* ** update chain, */ error_code = MFS_Put_fat(drive_ptr, new_cluster_number, next_cluster); if ( error_code ) { return(error_code); } if ( handle->PREVIOUS_CLUSTER ) { error_code = MFS_Put_fat(drive_ptr,handle->PREVIOUS_CLUSTER, new_cluster_number ); if ( error_code ) { return(error_code); } } else { clustod(handle->DIR_ENTRY.HFIRST_CLUSTER, handle->DIR_ENTRY.LFIRST_CLUSTER, new_cluster_number); } handle->PREVIOUS_CLUSTER = new_cluster_number; ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_LOCK, &drive_ptr->DRV_NUM); } else { handle->PREVIOUS_CLUSTER = cluster_number+i; } temp_buffer_ptr += drive_ptr->CLUSTER_SIZE_BYTES; sector_number += drive_ptr->BPB.SECTORS_PER_CLUSTER; } #endif } /* Unlock device under MFS */ ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_UNLOCK, &drive_ptr->DRV_NUM); switch ( error ) { case IO_ERROR_WRITE_PROTECTED: error = MFS_DISK_IS_WRITE_PROTECTED; break; case IO_ERROR_WRITE: error = MFS_WRITE_FAULT; break; case IO_ERROR_WRITE_ACCESS: error = MFS_SECTOR_NOT_FOUND; break; case IO_ERROR_READ: error = MFS_READ_FAULT; break; case IO_ERROR_READ_ACCESS: error = MFS_SECTOR_NOT_FOUND; break; default: break; } return(error); }