/*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_Read_fat ( MFS_DRIVE_STRUCT_PTR drive_ptr, uint_32 offset /*[IN] the offset byte in the FAT that we are looking for */ ) { uint_32 needed_sector,needed_end_sector,i; _mfs_error error_code; error_code = MFS_NO_ERROR; needed_sector = offset / drive_ptr->BPB.SECTOR_SIZE; MFS_LOG(printf("\nRead fat: Offset = %d\n", offset)); if ( drive_ptr->FAT_TYPE == MFS_FAT12 ) { needed_end_sector = (offset+1)/ drive_ptr->BPB.SECTOR_SIZE; } else { needed_end_sector = needed_sector; } /* ** If the FAT fragment that we already have in memory is requested, do ** not update or re-read it. */ if ( (needed_sector < drive_ptr->FAT_CACHE_START) || (needed_end_sector > drive_ptr->FAT_CACHE_START + drive_ptr->FAT_CACHE_SIZE - 1) ) { error_code = MFS_Flush_fat_cache(drive_ptr); if ( error_code ) { return(error_code); } if ( drive_ptr->FAT_TYPE == MFS_FAT32 ) { if ( needed_sector > (drive_ptr->BPB32.FAT_SIZE - drive_ptr->FAT_CACHE_SIZE) ) { needed_sector = drive_ptr->BPB32.FAT_SIZE - drive_ptr->FAT_CACHE_SIZE; } } else { if ( needed_sector > (drive_ptr->BPB.SECTORS_PER_FAT - drive_ptr->FAT_CACHE_SIZE) ) { needed_sector = drive_ptr->BPB.SECTORS_PER_FAT - drive_ptr->FAT_CACHE_SIZE; } } for ( i=0;i<(drive_ptr->FAT_CACHE_SIZE) && (error_code==MFS_NO_ERROR);i++ ) { error_code = MFS_Read_device_sector (drive_ptr, drive_ptr->FAT_START_SECTOR + needed_sector + i, (pointer) &drive_ptr->FAT_CACHE_PTR[drive_ptr->BPB.SECTOR_SIZE*i]); } if ( error_code == MFS_NO_ERROR ) { drive_ptr->FAT_CACHE_START = needed_sector; drive_ptr->FAT_CACHE_DIRTY = FALSE; } } return(error_code); }
/*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); }
/*FUNCTION*------------------------------------------------------------------- * * Function Name : MFS_Read_device_sector * Returned Value : error_code * Comments : * Readsone sector into the DATA_SECTOR buffer *END*---------------------------------------------------------------------*/ _mfs_error MFS_Read_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 sector_ptr ) { uint_32 new_cluster_number, next_cluster, bad_cluster_number; uint_32 i; uint_32 retries, attempts; uint_32 new_sector_number, error_code, no_of_sectors; char_ptr temp_buffer_ptr; int_32 num, expect_num, shifter, seek_loc, tmp; _mfs_error error; error = MFS_NO_ERROR; if ( sector_number > drive_ptr->BPB.MEGA_SECTORS ) { return(MFS_SECTOR_NOT_FOUND); } MFS_LOG(printf("MFS_Read_device_sector %d", sector_number)); 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; } fseek(drive_ptr->DEV_FILE_PTR, seek_loc, IO_SEEK_SET); while ( expect_num > 0 && attempts++ < MFSCFG_MAX_READ_RETRIES ) { num = read(drive_ptr->DEV_FILE_PTR, sector_ptr, expect_num); if ( num == IO_ERROR ) { break; } expect_num -= num; sector_ptr += num << shifter; } if ( expect_num > 0 ) { error = drive_ptr->DEV_FILE_PTR->ERROR; } /* Unlock device under MFS */ ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_UNLOCK, &drive_ptr->DRV_NUM); if ( error == IO_ERROR_READ ) { error = MFS_READ_FAULT; } else if ( error == IO_ERROR_READ_ACCESS ) { error = MFS_SECTOR_NOT_FOUND; } return error; }
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; } }
/*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; }
/*FUNCTION*------------------------------------------------------------------- * * Function Name : MFS_Read_device_sectors * Returned Value : error_code * Comments : * Reads consecutive sectors into given buffer *END*---------------------------------------------------------------------*/ _mfs_error MFS_Read_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, shifter, seek_loc; _mfs_error error; error = MFS_NO_ERROR; if ( sector_number+sector_count-1 > drive_ptr->BPB.MEGA_SECTORS ) { return(MFS_SECTOR_NOT_FOUND); } MFS_LOG(printf("MFS_Read_device_sectors %d %d", sector_number, sector_count)); 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); attempts = 0; while ( expect_num > 0 && attempts <= max_retries ) { num = read(drive_ptr->DEV_FILE_PTR, buffer_ptr, expect_num); if ( num == IO_ERROR ) { error = IO_ERROR_READ; break; } if ( num > 0 ) { expect_num -= num; buffer_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; } if ( error == IO_ERROR_READ ) { error = MFS_READ_FAULT; } else if ( error == IO_ERROR_READ_ACCESS ) { error = MFS_SECTOR_NOT_FOUND; } else if ( (error == MFS_NO_ERROR) && (expect_num > 0) ) { /* Ensure that error code is always set if less than requested data was read */ error = MFS_READ_FAULT; } if (processed) *processed = ((sector_count<<shifter) - expect_num) >> shifter; return error; }