public void WriteSectors(long firstSectorIndex, byte[] data) { int sectorCount; long lastSectorIndexToWrite; long lastClusterVCNToWrite; int bytesPerSector = m_volume.BytesPerSector; int sectorsPerCluster = m_volume.SectorsPerCluster; ulong firstBytePosition = (ulong)firstSectorIndex * (uint)bytesPerSector; ulong nextBytePosition = firstBytePosition + (uint)data.Length; if (data.Length % bytesPerSector > 0) { int paddedLength = (int)Math.Ceiling((double)data.Length / bytesPerSector) * bytesPerSector; // last sector could be partial, we must zero-fill it before write sectorCount = paddedLength / bytesPerSector; lastSectorIndexToWrite = firstSectorIndex + sectorCount - 1; lastClusterVCNToWrite = lastSectorIndexToWrite / sectorsPerCluster; if (lastClusterVCNToWrite == HighestVCN) { byte[] paddedData = new byte[paddedLength]; Array.Copy(data, paddedData, data.Length); data = paddedData; } else { // only the last sector can be partial throw new ArgumentException("Cannot write partial sector"); } } else { sectorCount = data.Length / bytesPerSector; lastSectorIndexToWrite = firstSectorIndex + sectorCount - 1; lastClusterVCNToWrite = lastSectorIndexToWrite / sectorsPerCluster; } long firstClusterVCN = firstSectorIndex / sectorsPerCluster; if (firstClusterVCN < LowestVCN || lastClusterVCNToWrite > HighestVCN) { string message = String.Format("Cluster VCN {0}-{1} is not within the valid range ({2}-{3})", firstClusterVCN, lastClusterVCNToWrite, LowestVCN, HighestVCN); throw new ArgumentOutOfRangeException(message); } if (firstBytePosition > ValidDataLength) { // We need to zero-fill all the the bytes up to ValidDataLength long firstSectorIndexToFill = (long)(ValidDataLength / (uint)bytesPerSector); int transferSizeInSectors = Settings.MaximumTransferSizeLBA; for (long sectorIndexToFill = firstSectorIndexToFill; sectorIndexToFill < firstSectorIndex; sectorIndexToFill += transferSizeInSectors) { int sectorsToWrite = (int)Math.Min(transferSizeInSectors, firstSectorIndex - firstSectorIndexToFill); byte[] fillData = new byte[sectorsToWrite * bytesPerSector]; if (sectorIndexToFill == firstSectorIndexToFill) { int bytesToRetain = (int)(ValidDataLength % (uint)bytesPerSector); if (bytesToRetain > 0) { byte[] dataToRetain = ReadSectors(firstSectorIndexToFill, 1); Array.Copy(dataToRetain, 0, fillData, 0, bytesToRetain); } } WriteSectors(sectorIndexToFill, fillData); } } KeyValuePairList <long, int> sequence = m_attributeRecord.DataRunSequence.TranslateToLBN(firstSectorIndex, sectorCount, sectorsPerCluster); long bytesWritten = 0; foreach (KeyValuePair <long, int> run in sequence) { byte[] sectors = new byte[run.Value * bytesPerSector]; Array.Copy(data, bytesWritten, sectors, 0, sectors.Length); m_volume.WriteSectors(run.Key, sectors, m_contentType); bytesWritten += sectors.Length; } if (nextBytePosition > ValidDataLength) { m_attributeRecord.ValidDataLength = nextBytePosition; if (m_fileRecord != null) { m_volume.UpdateFileRecord(m_fileRecord); } } }