// The maximum NTFS file size is 2^64 bytes, so total number of file clusters can be represented using long public void AllocateAdditionalClusters(NTFSVolume volume, long clustersToAllocate) { ulong desiredStartLCN = (ulong)DataRunSequence.DataLastLCN; KeyValuePairList <ulong, long> freeClusterRunList = volume.AllocateClusters(desiredStartLCN, clustersToAllocate); for (int index = 0; index < freeClusterRunList.Count; index++) { ulong runStartLCN = freeClusterRunList[index].Key; long runLength = freeClusterRunList[index].Value; bool mergeWithLastRun = (index == 0 && runStartLCN == desiredStartLCN); if (mergeWithLastRun) { // we append this run to the last run DataRun lastRun = DataRunSequence[DataRunSequence.Count - 1]; lastRun.RunLength += (long)runLength; HighestVCN += (long)runLength; } else { DataRun run = new DataRun(); ulong previousLCN = (ulong)DataRunSequence.LastDataRunStartLCN; run.RunOffset = (long)(runStartLCN - previousLCN); run.RunLength = (long)runLength; HighestVCN += runLength; DataRunSequence.Add(run); } } }
// Data run NULL terminator here // I've noticed that Windows Server 2003 puts 0x00 0x01 here for the $MFT FileRecord, seems to have no effect // (I've set it to 0 for the $MFT FileRecord in the MFT and the MFT mirror, and chkdsk did not report a problem. public NonResidentAttributeRecord(byte[] buffer, int offset) : base(buffer, offset) { LowestVCN = (long)LittleEndianConverter.ToUInt64(buffer, offset + 0x10); HighestVCN = (long)LittleEndianConverter.ToUInt64(buffer, offset + 0x18); ushort mappingPairsOffset = LittleEndianConverter.ToUInt16(buffer, offset + 0x20); CompressionUnitSize = LittleEndianConverter.ToUInt16(buffer, offset + 0x22); ulong allocatedLength = LittleEndianConverter.ToUInt64(buffer, offset + 0x28); FileSize = LittleEndianConverter.ToUInt64(buffer, offset + 0x30); ValidDataLength = LittleEndianConverter.ToUInt64(buffer, offset + 0x38); int position = offset + mappingPairsOffset; while (position < offset + this.StoredRecordLength) { DataRun run = new DataRun(); int length = run.Read(buffer, position); position += length; // Length 1 means there was only a header byte (i.e. terminator) if (length == 1) { break; } m_dataRunSequence.Add(run); } if ((HighestVCN - LowestVCN + 1) != m_dataRunSequence.DataClusterCount) { throw new InvalidDataException("Invalid non-resident attribute record"); } }
public DataRunSequence Clone() { DataRunSequence clone = new DataRunSequence(this.Count); foreach (DataRun run in this) { clone.Add(run.Clone()); } return(clone); }