/// <summary> /// This test checks that attributes are deep cloned when assembled from FileRecordSegment list and sliced into FileRecordSegment list. /// </summary> public static void AttributeCloneTest() { byte minorNTFSVersion = 1; int bytesPerFileRecordSegment = 1024; FileRecordSegment baseSegment = new FileRecordSegment(30, 1); FileRecordSegment segment2 = new FileRecordSegment(31, 1, baseSegment.SegmentReference); FileNameRecord fileNameRecord = new FileNameRecord(NTFSVolume.RootDirSegmentReference, "john.txt", false, DateTime.Now); FileNameAttributeRecord fileNameAttribute = new FileNameAttributeRecord(String.Empty); fileNameAttribute.Record = fileNameRecord; NonResidentAttributeRecord dataRecord = new NonResidentAttributeRecord(AttributeType.Data, String.Empty); baseSegment.ImmediateAttributes.Add(fileNameAttribute); baseSegment.ImmediateAttributes.Add(dataRecord); dataRecord.DataRunSequence.Add(new DataRun(5, 0)); byte[] segmentBytesBefore = baseSegment.GetBytes(bytesPerFileRecordSegment, minorNTFSVersion, false); List <FileRecordSegment> segments = new List <FileRecordSegment>(); segments.Add(baseSegment); segments.Add(segment2); FileRecord fileRecord = new FileRecord(segments); ((NonResidentAttributeRecord)fileRecord.DataRecord).DataRunSequence[0].RunLength = 8; fileRecord.FileNameRecord.ParentDirectory = new MftSegmentReference(8, 8); fileRecord.FileNameRecord.FileName = "d"; byte[] segmentBytesAfter = baseSegment.GetBytes(bytesPerFileRecordSegment, minorNTFSVersion, false); if (!ByteUtils.AreByteArraysEqual(segmentBytesBefore, segmentBytesAfter)) { throw new Exception("Test failed"); } fileRecord.UpdateSegments(1024, 1); byte[] segmentBytesBefore2 = fileRecord.Segments[0].GetBytes(bytesPerFileRecordSegment, minorNTFSVersion, false); ((NonResidentAttributeRecord)fileRecord.DataRecord).DataRunSequence[0].RunLength = 10; fileRecord.FileNameRecord.FileName = "x"; byte[] segmentBytesAfter2 = fileRecord.Segments[0].GetBytes(bytesPerFileRecordSegment, minorNTFSVersion, false); if (!ByteUtils.AreByteArraysEqual(segmentBytesBefore2, segmentBytesAfter2)) { throw new Exception("Test failed"); } }
public static void CreateVolumeWithPendingFileCreation(string path, long size, int bytesPerCluster, string volumeLabel, string fileName, byte[] fileData) { VirtualHardDisk disk = VirtualHardDisk.CreateFixedDisk(path, size); disk.ExclusiveLock(); Partition partition = NTFSFormatTests.CreatePrimaryPartition(disk); NTFSVolume volume = NTFSVolumeCreator.Format(partition, bytesPerCluster, volumeLabel); long segmentNumber = MasterFileTable.FirstUserSegmentNumber; FileNameRecord fileNameRecord = new FileNameRecord(MasterFileTable.RootDirSegmentReference, fileName, false, DateTime.Now); FileRecordSegment fileRecordSegment = CreateFileRecordSegment(segmentNumber, fileNameRecord, fileData); ulong dataStreamOffset = (ulong)(segmentNumber * volume.BytesPerFileRecordSegment); byte[] redoData = fileRecordSegment.GetBytes(volume.BytesPerFileRecordSegment, volume.MinorVersion, false); MftSegmentReference mftFileReference = new MftSegmentReference(0, 1); AttributeRecord mftDataRecord = volume.GetFileRecord(mftFileReference).GetAttributeRecord(AttributeType.Data, String.Empty); AttributeRecord mftBitmapRecord = volume.GetFileRecord(mftFileReference).GetAttributeRecord(AttributeType.Bitmap, String.Empty); uint transactionID = volume.LogClient.AllocateTransactionID(); volume.LogClient.WriteLogRecord(mftFileReference, mftDataRecord, dataStreamOffset, volume.BytesPerFileRecordSegment, NTFSLogOperation.InitializeFileRecordSegment, redoData, NTFSLogOperation.Noop, new byte[0], transactionID); long bitmapVCN = segmentNumber / (volume.BytesPerCluster * 8); int bitOffsetInCluster = (int)(segmentNumber % (volume.BytesPerCluster * 8)); BitmapRange bitmapRange = new BitmapRange((uint)bitOffsetInCluster, 1); ulong bitmapStreamOffset = (ulong)(bitmapVCN * volume.BytesPerCluster); volume.LogClient.WriteLogRecord(mftFileReference, mftBitmapRecord, bitmapStreamOffset, volume.BytesPerCluster, NTFSLogOperation.SetBitsInNonResidentBitMap, bitmapRange.GetBytes(), NTFSLogOperation.Noop, new byte[0], transactionID); FileRecord parentDirectoryRecord = volume.GetFileRecord(MasterFileTable.RootDirSegmentReference); IndexData parentDirectoryIndex = new IndexData(volume, parentDirectoryRecord, AttributeType.FileName); byte[] fileNameRecordBytes = fileNameRecord.GetBytes(); long leafRecordVBN = 0; IndexRecord leafRecord = parentDirectoryIndex.ReadIndexRecord(leafRecordVBN); ulong indexAllocationOffset = (ulong)parentDirectoryIndex.ConvertToDataOffset(leafRecordVBN); int insertIndex = CollationHelper.FindIndexForSortedInsert(leafRecord.IndexEntries, fileNameRecordBytes, CollationRule.Filename); int insertOffset = leafRecord.GetEntryOffset(volume.BytesPerIndexRecord, insertIndex); AttributeRecord rootDirIndexAllocation = volume.GetFileRecord(MasterFileTable.RootDirSegmentReference).GetAttributeRecord(AttributeType.IndexAllocation, IndexHelper.GetIndexName(AttributeType.FileName)); IndexEntry indexEntry = new IndexEntry(fileRecordSegment.SegmentReference, fileNameRecord.GetBytes()); volume.LogClient.WriteLogRecord(MasterFileTable.RootDirSegmentReference, rootDirIndexAllocation, indexAllocationOffset, volume.BytesPerIndexRecord, 0, insertOffset, NTFSLogOperation.AddIndexEntryToAllocationBuffer, indexEntry.GetBytes(), NTFSLogOperation.Noop, new byte[0], transactionID, false); volume.LogClient.WriteForgetTransactionRecord(transactionID, true); disk.ReleaseLock(); }