//************************************************************************* // Function: CETYPE FS_Flush(FSFILE* filePtr) // Summary: Update file information and FAT entry for the file // Input: // filePtr - Pointer to the file to flush to disk // Return Values: // CE_GOOD - File flushed successfully // Other code - Error closing the file // Description: // This function will update the directory entry for the // file pointed to by 'fo' with the information contained // in 'fo,' including the new file size and attributes. // Timestamp information will also be updated. The file // entry will then be written to the device. Finally, // the memory used for the specified file object will be // freed from the array of FSFILE objects. // Remarks: // A function to flush data to the device without closing // the file can be created by removing the portion of this // function that frees the memory and the line that clears // the write flag. //************************************************************************* CETYPE FS_Flush(FSFILE *filePtr) { //---------------------------------------------------------------- // Validate conditions and parameters //---------------------------------------------------------------- if (!SDFS_InitStatus) return CE_NOT_INIT; // FS is not initialized! if (NULL == filePtr) return CE_INVALID_ARGUMENT; //---------------------------------------------------------------- CETYPE RC; //---------------------------------------------------------------- if ( !FS_IsReadOnly(filePtr) ) { // Save directory entry for the file RC = SDFS_DataCacheWrite( filePtr->dirLBA, &filePtr->dirFileEntry, filePtr->dirOffset, sizeof(DIRENTRY) ); if (CE_GOOD != RC) return RC; // Flush data if ( (RC = SDFS_DataCacheFlush()) != CE_GOOD) return RC; } //---------------------------------------------------------------- return CE_GOOD; }
//********************************************************************************* // Function: CETYPE FS_Write(FSFILE* filePtr, const void* origin, WORD length) // Summary: Write data to a file // Conditions: File opened in FS_CREATE_NEW, FS_APPEND, or FS_OPEN_EXISTING mode // Input: // filePtr - Pointer to file structure // origin - Pointer to source buffer // length - Length of the source buffer (data to write) // Return: // CETYPE - Error code (expected: CE_GOOD) // Description: // The FS_Write function will write data to a file. First, the sector // that corresponds to the current position in the file will be loaded // (if it hasn't already been cached in the global data buffer). Data // will then be written to the device from the specified buffer until // the specified amount has been written. // If the end of a cluster is reached, the next cluster will be // loaded, unless the end-of-file flag for the specified file has been // set. If it has, a new cluster will be allocated to the file. Finally, // the new position and filesize will be stored in the FSFILE object. //********************************************************************************* CETYPE FS_Write(FSFILE* filePtr, const void* origin, WORD length ) { //---------------------------------------------------------------- // Validate conditions and parameters //---------------------------------------------------------------- if (!SDFS_InitStatus) return CE_NOT_INIT; // FS is not initialized! if (NULL == filePtr) return CE_INVALID_ARGUMENT; //---------------------------------------------------------------- // Check if the file attributes allow write if( (filePtr->dirFileEntry.DIR_Attr & ATTR_READONLY) == ATTR_READONLY ) return CE_READONLY; // Check if pointer is valid if (origin == NULL) return CE_INVALID_ARGUMENT; // Check if length is valid if (length == 0) return CE_INVALID_ARGUMENT; //----------------------------------------------------------------- DWORD LBA; BYTE* ptrFrom = (BYTE*)origin; WORD ChunkSize; CETYPE RC; // Write data to the file //{ //------------------------------------------------------------ // Loop while writing bytes, exit loop if: // * All bytes are written // * Error encountered //------------------------------------------------------------ while (length > 0) { //---------------------------------------------------- // Make sure we have defined a place to write to //---------------------------------------------------- //{ if (filePtr->fileCrntSecPos == SDFS_VolumeInfo.sectorSize) { //---------------------------------------------------- // Current sector is filled in... //---------------------------------------------------- // NOTE: fileCrntSec is a 0-based counter (index) //---------------------------------------------------- if (filePtr->fileCrntSec == SDFS_VolumeInfo.SecPerClus - 1) { //---------------------------------------------------- // Current cluster is exhausted - move to the next one //---------------------------------------------------- RC = SDFS_ClusterGetNext(filePtr); if ( CE_EOF == RC ) // Oops! Reached end-of-file - try to add another cluster RC = SDFS_ClusterAllocateNew(filePtr); //---------------------------------------------------- if ( CE_GOOD != RC ) // Bad luck - no cluster to advance to! return RC; } else { // It is safe to move to the next sector in the current cluster filePtr->fileCrntSec++; // move to the next sector filePtr->fileCrntSecPos = 0; // reset position } //---------------------------------------------------- } //} //----------------------------------------------------------------- LBA = SDFS_FATClusterToLBA( filePtr->fileCrntCls) + filePtr->fileCrntSec; // add the sector number to it ChunkSize = length <= SDFS_VolumeInfo.sectorSize - filePtr->fileCrntSecPos ? length : SDFS_VolumeInfo.sectorSize - filePtr->fileCrntSecPos; //----------------------------------------------------------------- if (CE_GOOD != (RC = SDFS_DataCacheWrite (LBA, ptrFrom, filePtr->fileCrntSecPos, ChunkSize ))) return RC; //----------------------------------------------------------------- length -= ChunkSize; ptrFrom += ChunkSize; //---------------------- filePtr->fileCrntSecPos += ChunkSize; filePtr->fileSeek += ChunkSize; if (filePtr->dirFileEntry.DIR_FileSize < filePtr->fileSeek) filePtr->dirFileEntry.DIR_FileSize = filePtr->fileSeek; } //----------------------------------- return CE_GOOD; } // write