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 * * Get an unused cluster number. Assumes that the FAT has been read * Assumes drive SEM is locked. * * \param[in] drive_ptr The drive on which to operate. * \param[in] cluster_number First cluster number to search. * * \return uint32_t Cluster_number, 0xffff means that none is available */ uint32_t MFS_Find_unused_cluster_from( MFS_DRIVE_STRUCT_PTR drive_ptr, uint32_t cluster_number) { uint32_t max_clusters, cluster; _mfs_error error_code; uint32_t cluster_status; 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 Get number of free clusters on the disk. * * \param drive_ptr * \param free_clusters_ptr * * \return _mfs_error */ _mfs_error MFS_Get_disk_free_space_internal( MFS_DRIVE_STRUCT_PTR drive_ptr, uint32_t *free_clusters_ptr) { uint32_t last_cluster; uint32_t k; uint32_t free_slots; _mfs_error error_code = MFS_NO_ERROR; uint32_t cluster_status; last_cluster = drive_ptr->LAST_CLUSTER; if (drive_ptr->FREE_COUNT == FSI_UNKNOWN) { free_slots = 0; 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_UNUSED) { free_slots++; } } if (error_code == MFS_NO_ERROR) { drive_ptr->FREE_COUNT = free_slots; } } else { free_slots = drive_ptr->FREE_COUNT; } if (free_clusters_ptr != NULL) { *free_clusters_ptr = free_slots; } return error_code; }
/*! * \brief Follow a chain of clusters and mark the entries as unused. * * \param[in] drive_ptr The drive on which to operate. * \param[in] cluster_number First cluster number to release. * * \return _mfs_error */ _mfs_error MFS_Release_chain( MFS_DRIVE_STRUCT_PTR drive_ptr, uint32_t cluster_number) { uint32_t next_cluster; _mfs_error error_code; 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; } error_code = MFS_Put_fat(drive_ptr, cluster_number, CLUSTER_UNUSED); if (error_code) { break; } /* Invalidation of data sectors of released chain here may certainly save some write operations but it is mostly a corner case */ error_code = MFS_sector_cache_invalidate(drive_ptr, CLUSTER_TO_SECTOR(drive_ptr, cluster_number), drive_ptr->SECTORS_PER_CLUSTER); if (error_code) { break; } cluster_number = next_cluster; } while (cluster_number != CLUSTER_EOF); } else { error_code = MFS_NO_ERROR; } return (error_code); }
/*! * \brief Get the number of bad clusters in the file system. * * \param drive_ptr * \param bad_clusters_ptr * * \return _mfs_error */ _mfs_error MFS_Bad_clusters( MFS_DRIVE_STRUCT_PTR drive_ptr, uint32_t *bad_clusters_ptr) { uint32_t last_cluster; uint32_t k; uint32_t bad_slots; _mfs_error error_code; uint32_t cluster_status; if (bad_clusters_ptr == NULL) { return MFS_INVALID_POINTER; } bad_slots = 0; error_code = MFS_lock_and_enter(drive_ptr, 0); 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++; } } *bad_clusters_ptr = bad_slots; MFS_leave_and_unlock(drive_ptr, 0); return error_code; }
_mfs_error MFS_next_data_sector( MFS_DRIVE_STRUCT_PTR drive_ptr, MFS_HANDLE_PTR handle, uint32_t *sector_index_ptr, uint32_t *sector_number_ptr ) { _mfs_error error = MFS_NO_ERROR; uint32_t next_cluster; if ( handle->CURRENT_CLUSTER != CLUSTER_EOF ) { (*sector_index_ptr)++; if ( *sector_index_ptr >= drive_ptr->BPB.SECTORS_PER_CLUSTER ) { // New cluster error = MFS_get_cluster_from_fat(drive_ptr, handle->CURRENT_CLUSTER, &next_cluster); if ( error == MFS_NO_ERROR ) { handle->PREVIOUS_CLUSTER = handle->CURRENT_CLUSTER; handle->CURRENT_CLUSTER = next_cluster; *sector_index_ptr = 0; if ( next_cluster == CLUSTER_EOF ) { error = MFS_EOF; } } } if ( error == MFS_NO_ERROR ) { *sector_number_ptr = CLUSTER_TO_SECTOR(handle->CURRENT_CLUSTER) + *sector_index_ptr; } } else { error = MFS_EOF; } return error; }
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); }
uint_32 MFS_Get_disk_free_space_internal ( MFS_DRIVE_STRUCT_PTR drive_ptr, uint_32_ptr error_ptr ) { uint_32 last_cluster, k, free_slots; uint_32 error_code = MFS_NO_ERROR; uint_32 cluster_status; last_cluster = drive_ptr->LAST_CLUSTER; if ( drive_ptr->FREE_COUNT == FSI_UNKNOWN ) { free_slots = 0; 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_UNUSED ) { free_slots++; } } drive_ptr->FREE_COUNT = free_slots; } else { free_slots = drive_ptr->FREE_COUNT; } MFS_set_error_and_return(error_ptr, error_code, free_slots); }
_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); }
_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); }
/*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); }
/*! * \brief Find a free cluster, follow a chain and add it to the chain. * * \param[in] drive_ptr The drive on which to operate. * \param[in] cluster_number Number of a cluster within the chain. * \param[in] num_clusters Number of clusters to append to chain. * \param[in] added_cluster Pointer to the place where we should put the # of the first new cluster. * * \return _mfs_error */ _mfs_error MFS_Extend_chain( MFS_DRIVE_STRUCT_PTR drive_ptr, uint32_t cluster_number, uint32_t num_clusters, uint32_t *added_cluster) { uint32_t next_cluster; uint32_t extended; _mfs_error error_code; if (cluster_number < CLUSTER_MIN_GOOD || cluster_number > drive_ptr->LAST_CLUSTER) { return MFS_INVALID_CLUSTER_NUMBER; } if (num_clusters <= 0) { return MFS_NO_ERROR; } /* Find the end of the chain */ next_cluster = cluster_number; do { cluster_number = next_cluster; error_code = MFS_get_cluster_from_fat(drive_ptr, cluster_number, &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); extended = 0; while (num_clusters) { /* 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) { break; /* Condition handled after the loop */ } /* Link the free cluster to the chain, at the end */ error_code = MFS_Put_fat(drive_ptr, cluster_number, next_cluster); if (error_code != MFS_NO_ERROR) { return error_code; } if (extended == 0 && added_cluster != NULL) { *added_cluster = next_cluster; } extended++; cluster_number = next_cluster; num_clusters--; } /* If the chain was extended, write EOF to it's last link */ if (extended) { error_code = MFS_Put_fat(drive_ptr, cluster_number, CLUSTER_EOF); } if (num_clusters && !error_code) { error_code = MFS_DISK_FULL; } 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; } }
_mfs_error MFS_Increment_dir_index ( MFS_DRIVE_STRUCT_PTR drive_ptr, /*[IN] the drive on which to operate */ uint_32_ptr cluster_ptr, /*[IN/OUT] the initial/next cluster # */ uint_32_ptr index_ptr, /*[IN/OUT] the initial/next index */ uint_32_ptr prev_cluster_ptr /*[IN/OUT] the prev cluster # */ ) { uint_32 index; uint_32 cluster; _mfs_error error_code; error_code = MFS_NO_ERROR; index = *index_ptr; cluster = *cluster_ptr; index++; if ( !(index & (drive_ptr->ENTRIES_PER_SECTOR-1)) ) { /* ** if the index count LSB's wrapped to 0 (new sector) */ if ( cluster != 0 ) { if ( INDEX_TO_SECTOR (index) >= drive_ptr->BPB.SECTORS_PER_CLUSTER ) { /* ** If we are over the size of a cluster */ error_code = MFS_get_cluster_from_fat(drive_ptr,cluster, &cluster); if ( error_code == MFS_NO_ERROR ) { index = 0; } } } else { if ( index >= drive_ptr->BPB.ROOT_ENTRIES ) { index = 0; cluster = CLUSTER_INVALID; } } } if ( (cluster != *cluster_ptr) && (cluster != CLUSTER_INVALID) ) { if ( prev_cluster_ptr != NULL ) { *prev_cluster_ptr = *cluster_ptr; } } *index_ptr = index; *cluster_ptr = cluster; return(error_code); }