public override int Write(object fileNode, object fileDesc, IntPtr buffer, ulong offset, uint length, bool writeToEndOfFile, bool constrainedIo, out uint bytesTransferred, out FileInfo fileInfo) { if (fileNode is FileNode node && fileDesc is FileMetadata metadata) { Logger.LogTrace( $"Request {nameof ( Write )} to \"{metadata . Name}\", start from {offset} with length {length}({( ( long ) length ) . BytesCountToHumanString ( )})."); if (writeToEndOfFile) { offset = ( ulong )metadata.Size; } if (!constrainedIo) { ResizeFile( node, Math.Max(metadata.Size, ( long )offset + length)); length = ( uint )Math.Min(metadata.Size - ( long )offset, length); } int startBlockSequence = ( int )(offset / ( ulong )BlockSize); int endBlockSequence = ( int )((offset + length + ( ulong )BlockSize - 1) / ( ulong )BlockSize); int currentByteSequence = 0; int currentBlockSequence = startBlockSequence; CachedBlock currentBlock = node.GetBlock(currentBlockSequence); #region firstBlock int firstByteStartFrom = ( int )(offset % ( ulong )BlockSize); int currentBlockCopyByteCount = ( int )Math.Min( BlockSize - firstByteStartFrom, length - currentByteSequence); currentBlock.IsModified = true; Marshal.Copy( buffer + currentByteSequence, currentBlock.Content, firstByteStartFrom, currentBlockCopyByteCount); currentByteSequence += currentBlockCopyByteCount; currentBlockSequence++; #endregion firstByteStartFrom = 0; for ( ; currentBlockSequence < endBlockSequence; currentBlockSequence++) { currentBlock = node.GetBlock(currentBlockSequence); currentBlockCopyByteCount = ( int )Math.Min( BlockSize - firstByteStartFrom, length - currentByteSequence); currentBlock.IsModified = true; Marshal.Copy( buffer + currentByteSequence, currentBlock.Content, firstByteStartFrom, currentBlockCopyByteCount); currentByteSequence += currentBlockCopyByteCount; } bytesTransferred = ( uint )currentByteSequence; fileInfo = metadata.FileInfo; Logger.LogDebug( $"Written to \"{metadata . Name}\", start from {offset} with length {bytesTransferred}({( ( long ) bytesTransferred ) . BytesCountToHumanString ( )})."); return(STATUS_SUCCESS); } throw GetIoExceptionWithNtStatus(STATUS_INVALID_HANDLE); }
public override int Read(object fileNode, object fileDesc, IntPtr buffer, ulong offset, uint length, out uint bytesTransferred) { if (fileNode is FileNode node && fileDesc is FileMetadata metadata) { Logger.LogTrace( $"Request {nameof ( Read )} from \"{metadata . Name}\", start from {offset} with length {length}({( ( long ) length ) . BytesCountToHumanString ( )})."); if (offset >= ( ulong )metadata.Size) { bytesTransferred = default; return(STATUS_END_OF_FILE); } length = ( uint )Math.Min(length, metadata.Size - ( long )offset); int startBlockSequence = ( int )(offset / ( ulong )BlockSize); int endBlockSequence = ( int )((offset + length + ( ulong )BlockSize - 1) / ( ulong )BlockSize); endBlockSequence = Math.Min( endBlockSequence, metadata.AllocatedBlockCount - 1); int currentByteSequence = 0; int currentBlockSequence = startBlockSequence; #region firstBlock CachedBlock currentBlock = node.GetBlock(currentBlockSequence); int firstByteStartFrom = ( int )(offset % ( ulong )BlockSize); int currentBlockCopyByteCount = ( int )Math.Min( BlockSize - firstByteStartFrom, length - currentByteSequence); Marshal.Copy( currentBlock.Content, firstByteStartFrom, buffer + currentByteSequence, currentBlockCopyByteCount); currentByteSequence += currentBlockCopyByteCount; currentBlockSequence++; #endregion firstByteStartFrom = 0; for ( ; currentBlockSequence < endBlockSequence; currentBlockSequence++) { currentBlock = node.GetBlock(currentBlockSequence); currentBlockCopyByteCount = ( int )Math.Min( BlockSize - firstByteStartFrom, length - currentByteSequence); Marshal.Copy( currentBlock.Content, firstByteStartFrom, buffer + currentByteSequence, currentBlockCopyByteCount); currentByteSequence += currentBlockCopyByteCount; } bytesTransferred = ( uint )currentByteSequence; Logger.LogDebug( $"Read from \"{metadata . Name}\", start from {offset} with length {bytesTransferred}({( ( long ) bytesTransferred ) . BytesCountToHumanString ( )})."); return(STATUS_SUCCESS); } throw GetIoExceptionWithNtStatus(STATUS_INVALID_HANDLE); }