/** * @public * @brief Writes a char to a FILE. * * @param pFile FILE Pointer. * @param pa_cValue Char to be placed in the file. * * @return Returns the value written to the file, or a value less than 0. * **/ FF_T_SINT32 FF_PutC(FF_FILE *pFile, FF_T_UINT8 pa_cValue) { FF_BUFFER *pBuffer; FF_T_UINT32 iItemLBA; FF_T_UINT32 iRelPos; FF_T_UINT32 nClusterDiff; FF_ERROR Error; if(!pFile) { // Ensure we don't have a Null file pointer on a Public interface. return FF_ERR_NULL_POINTER; } if(!(pFile->Mode & FF_MODE_WRITE)) { return FF_ERR_FILE_NOT_OPENED_IN_WRITE_MODE; } // Make sure a write is after the append point. if((pFile->Mode & FF_MODE_APPEND)) { if(pFile->FilePointer < pFile->Filesize) { FF_Seek(pFile, 0, FF_SEEK_END); } } iRelPos = FF_getMinorBlockEntry(pFile->pIoman, pFile->FilePointer, 1); // Handle File Space Allocation. Error = FF_ExtendFile(pFile, pFile->FilePointer + 1); if(Error) { return Error; } nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster; if(nClusterDiff) { if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) { pFile->AddrCurrentCluster = FF_TraverseFAT(pFile->pIoman, pFile->AddrCurrentCluster, nClusterDiff, &Error); if(Error) { return Error; } pFile->CurrentCluster += nClusterDiff; } } iItemLBA = FF_Cluster2LBA(pFile->pIoman, pFile->AddrCurrentCluster) + FF_getMajorBlockNumber(pFile->pIoman, pFile->FilePointer, (FF_T_UINT16) 1); iItemLBA = FF_getRealLBA (pFile->pIoman, iItemLBA) + FF_getMinorBlockNumber(pFile->pIoman, pFile->FilePointer, (FF_T_UINT16) 1); pBuffer = FF_GetBuffer(pFile->pIoman, iItemLBA, FF_MODE_WRITE); { if(!pBuffer) { return FF_ERR_DEVICE_DRIVER_FAILED; } FF_putChar(pBuffer->pBuffer, (FF_T_UINT16) iRelPos, pa_cValue); } FF_ReleaseBuffer(pFile->pIoman, pBuffer); pFile->FilePointer += 1; if(pFile->Filesize < (pFile->FilePointer)) { pFile->Filesize += 1; } return pa_cValue; }
NTSTATUS NTAPI FatiRead(PFAT_IRP_CONTEXT IrpContext) { ULONG NumberOfBytes; LARGE_INTEGER ByteOffset; PFILE_OBJECT FileObject; TYPE_OF_OPEN OpenType; PIO_STACK_LOCATION IrpSp = IrpContext->Stack; PFCB Fcb; PVCB Vcb; PCCB Ccb; PVOID Buffer; LONG BytesRead; FileObject = IrpSp->FileObject; NumberOfBytes = IrpSp->Parameters.Read.Length; ByteOffset = IrpSp->Parameters.Read.ByteOffset; if (NumberOfBytes == 0) { FatCompleteRequest(IrpContext, IrpContext->Irp, STATUS_SUCCESS); return STATUS_SUCCESS; } OpenType = FatDecodeFileObject(FileObject, &Vcb, &Fcb, &Ccb); DPRINT("FatiRead() Fcb %p, Name %wZ, Offset %d, Length %d, Handle %p\n", Fcb, &FileObject->FileName, ByteOffset.LowPart, NumberOfBytes, Fcb->FatHandle); /* Perform actual read */ if (IrpContext->MinorFunction & IRP_MN_MDL) { DPRINT1("MDL read\n"); } else { Buffer = FatMapUserBuffer(IrpContext->Irp); DPRINT("Normal cached read, buffer %p\n"); /* Set offset */ FF_Seek(Fcb->FatHandle, ByteOffset.LowPart, FF_SEEK_SET); /* Read */ BytesRead = FF_Read(Fcb->FatHandle, NumberOfBytes, 1, Buffer); DPRINT("Read %d bytes\n", BytesRead); /* Indicate we read requested amount of bytes */ IrpContext->Irp->IoStatus.Information = BytesRead; IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS; } /* Complete the request */ FatCompleteRequest(IrpContext, IrpContext->Irp, STATUS_SUCCESS); return STATUS_SUCCESS; }
DWORD WINAPI IOTestThread( LPVOID lpParam ) { THREAD hThread = (THREAD) lpParam; // Cast the thread param to the FF File. FF_T_UINT16 i; FF_T_UINT16 buf[1024]; for(i = 0; i < 1024; i++) { buf[i] = i; } while(!hThread->tKill) { i = (FF_T_UINT16) FF_Write(hThread->pFile, 2, 1024, (FF_T_UINT8 *) buf); FF_Seek(hThread->pFile, 0, FF_SEEK_SET); hThread->nThreadBytes += i; //Sleep(1000); } printf("Thread %d: Received Kill Signal\n", hThread->nThreadNum); hThread->isDead = FF_TRUE; return 0; }
/** * @public * @brief Writes data to a File. * * @param pFile FILE Pointer. * @param ElementSize Size of an Element of Data to be copied. (in bytes). * @param Count Number of Elements of Data to be copied. (ElementSize * Count must not exceed ((2^31)-1) bytes. (2GB). For best performance, multiples of 512 bytes or Cluster sizes are best. * @param buffer Byte-wise buffer containing the data to be written. * * @return **/ FF_T_SINT32 FF_Write(FF_FILE *pFile, FF_T_UINT32 ElementSize, FF_T_UINT32 Count, FF_T_UINT8 *buffer) { FF_T_UINT32 nBytes = ElementSize * Count; FF_T_UINT32 nBytesWritten = 0; FF_T_UINT32 nBytesToWrite; FF_IOMAN *pIoman; FF_BUFFER *pBuffer; FF_T_UINT32 nRelBlockPos; FF_T_UINT32 nItemLBA; FF_T_SINT32 RetVal = 0; FF_T_UINT16 sSectors; FF_T_UINT32 nRelClusterPos; FF_T_UINT32 nBytesPerCluster, nClusterDiff, nClusters; FF_ERROR Error; if(!pFile) { return FF_ERR_NULL_POINTER; } if(!(pFile->Mode & FF_MODE_WRITE)) { return FF_ERR_FILE_NOT_OPENED_IN_WRITE_MODE; } // Make sure a write is after the append point. if((pFile->Mode & FF_MODE_APPEND)) { if(pFile->FilePointer < pFile->Filesize) { FF_Seek(pFile, 0, FF_SEEK_END); } } pIoman = pFile->pIoman; nBytesPerCluster = (pIoman->pPartition->SectorsPerCluster * pIoman->BlkSize); // Extend File for atleast nBytes! // Handle file-space allocation Error = FF_ExtendFile(pFile, pFile->FilePointer + nBytes); if(Error) { return Error; } nRelBlockPos = FF_getMinorBlockEntry(pIoman, pFile->FilePointer, 1); // Get the position within a block. nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster; if(nClusterDiff) { if(pFile->CurrentCluster != FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) { pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff); pFile->CurrentCluster += nClusterDiff; } } nItemLBA = FF_Cluster2LBA(pIoman, pFile->AddrCurrentCluster); nItemLBA = FF_getRealLBA(pIoman, nItemLBA + FF_getMajorBlockNumber(pIoman, pFile->FilePointer, 1)) + FF_getMinorBlockNumber(pIoman, pFile->FilePointer, 1); if((nRelBlockPos + nBytes) < pIoman->BlkSize) { // Bytes to read are within a block and less than a block size. pBuffer = FF_GetBuffer(pIoman, nItemLBA, FF_MODE_WRITE); { memcpy((pBuffer->pBuffer + nRelBlockPos), buffer, nBytes); } FF_ReleaseBuffer(pIoman, pBuffer); pFile->FilePointer += nBytes; nBytesWritten = nBytes; //return nBytes; // Return the number of bytes read. } else { //---------- Write (memcpy) to a Sector Boundary if(nRelBlockPos != 0) { // Not on a sector boundary, at this point the LBA is known. nBytesToWrite = pIoman->BlkSize - nRelBlockPos; pBuffer = FF_GetBuffer(pIoman, nItemLBA, FF_MODE_WRITE); { // Here we copy to the sector boudary. memcpy((pBuffer->pBuffer + nRelBlockPos), buffer, nBytesToWrite); } FF_ReleaseBuffer(pIoman, pBuffer); nBytes -= nBytesToWrite; nBytesWritten += nBytesToWrite; pFile->FilePointer += nBytesToWrite; buffer += nBytesToWrite; } //---------- Write to a Cluster Boundary nRelClusterPos = FF_getClusterPosition(pIoman, pFile->FilePointer, 1); if(nRelClusterPos != 0 && nBytes >= nBytesPerCluster) { // Need to get to cluster boundary nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster; if(nClusterDiff) { if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) { pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff); pFile->CurrentCluster += nClusterDiff; } } nItemLBA = FF_Cluster2LBA(pIoman, pFile->AddrCurrentCluster); nItemLBA = FF_getRealLBA(pIoman, nItemLBA + FF_getMajorBlockNumber(pIoman, pFile->FilePointer, 1)) + FF_getMinorBlockNumber(pIoman, pFile->FilePointer, 1); sSectors = (FF_T_UINT16) (pIoman->pPartition->SectorsPerCluster - (nRelClusterPos / pIoman->BlkSize)); do { if(pIoman->pBlkDevice->fnWriteBlocks) { #ifdef FF_BLKDEV_USES_SEM FF_PendSemaphore(pFile->pIoman->pSemaphore); #endif RetVal = pFile->pIoman->pBlkDevice->fnWriteBlocks(buffer, nItemLBA, sSectors, pIoman->pBlkDevice->pParam); #ifdef FF_BLKDEV_USES_SEM FF_ReleaseSemaphore(pFile->pIoman->pSemaphore); #endif } if(RetVal == FF_ERR_DRIVER_BUSY) { FF_Yield(); FF_Sleep(FF_DRIVER_BUSY_SLEEP); } }while(RetVal == FF_ERR_DRIVER_BUSY); nBytesToWrite = sSectors * pIoman->BlkSize; nBytes -= nBytesToWrite; buffer += nBytesToWrite; nBytesWritten += nBytesToWrite; pFile->FilePointer += nBytesToWrite; } //---------- Write Clusters if(nBytes >= nBytesPerCluster) { //----- Thanks to Christopher Clark of DigiPen Institute of Technology in Redmond, US adding this traversal check. nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster; if(nClusterDiff) { if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) { pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff); pFile->CurrentCluster += nClusterDiff; } } //----- End of Contributor fix. nClusters = (nBytes / nBytesPerCluster); FF_WriteClusters(pFile, nClusters, buffer); nBytesToWrite = (nBytesPerCluster * nClusters); pFile->FilePointer += nBytesToWrite; nBytes -= nBytesToWrite; buffer += nBytesToWrite; nBytesWritten += nBytesToWrite; } //---------- Write Remaining Blocks if(nBytes >= pIoman->BlkSize) { sSectors = (FF_T_UINT16) (nBytes / pIoman->BlkSize); nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster; if(nClusterDiff) { if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) { pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff); pFile->CurrentCluster += nClusterDiff; } } nItemLBA = FF_Cluster2LBA(pIoman, pFile->AddrCurrentCluster); nItemLBA = FF_getRealLBA(pIoman, nItemLBA + FF_getMajorBlockNumber(pIoman, pFile->FilePointer, 1)) + FF_getMinorBlockNumber(pIoman, pFile->FilePointer, 1); do { if(pIoman->pBlkDevice->fnWriteBlocks) { #ifdef FF_BLKDEV_USES_SEM FF_PendSemaphore(pFile->pIoman->pSemaphore); #endif RetVal = pFile->pIoman->pBlkDevice->fnWriteBlocks(buffer, nItemLBA, sSectors, pIoman->pBlkDevice->pParam); #ifdef FF_BLKDEV_USES_SEM FF_ReleaseSemaphore(pFile->pIoman->pSemaphore); #endif } if(RetVal == FF_ERR_DRIVER_BUSY) { FF_Yield(); FF_Sleep(FF_DRIVER_BUSY_SLEEP); } }while(RetVal == FF_ERR_DRIVER_BUSY); nBytesToWrite = sSectors * pIoman->BlkSize; pFile->FilePointer += nBytesToWrite; nBytes -= nBytesToWrite; buffer += nBytesToWrite; nBytesWritten += nBytesToWrite; } //---------- Write (memcpy) Remaining Bytes if(nBytes > 0) { nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster; if(nClusterDiff) { if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) { pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff); pFile->CurrentCluster += nClusterDiff; } } nItemLBA = FF_Cluster2LBA(pIoman, pFile->AddrCurrentCluster); nItemLBA = FF_getRealLBA(pIoman, nItemLBA + FF_getMajorBlockNumber(pIoman, pFile->FilePointer, 1)) + FF_getMinorBlockNumber(pIoman, pFile->FilePointer, 1); pBuffer = FF_GetBuffer(pIoman, nItemLBA, FF_MODE_WRITE); { memcpy(pBuffer->pBuffer, buffer, nBytes); } FF_ReleaseBuffer(pIoman, pBuffer); nBytesToWrite = nBytes; pFile->FilePointer += nBytesToWrite; nBytes -= nBytesToWrite; buffer += nBytesToWrite; nBytesWritten += nBytesToWrite; } } if(pFile->FilePointer > pFile->Filesize) { pFile->Filesize = pFile->FilePointer; } return nBytesWritten; }