public void UpdateFileRecordSegment(FileRecordSegment recordSegment) { long segmentNumber = recordSegment.MftSegmentNumber; NTFSBootRecord bootRecord = m_volume.BootRecord; long firstSectorIndex = segmentNumber * m_volume.SectorsPerFileRecordSegment; byte[] recordSegmentBytes = recordSegment.GetBytes(bootRecord.FileRecordSegmentLength, m_volume.BytesPerCluster, m_volume.MinorVersion); m_mftRecord.NonResidentDataRecord.WriteDataSectors(m_volume, firstSectorIndex, recordSegmentBytes); }
public FileRecord CreateFile(List <FileNameRecord> fileNameRecords, uint transactionID) { if (fileNameRecords.Count == 0) { throw new ArgumentException(); } bool isDirectory = fileNameRecords[0].IsDirectory; MftSegmentReference segmentReference = AllocateFileRecordSegment(transactionID); FileRecordSegment fileRecordSegment = new FileRecordSegment(segmentReference.SegmentNumber, segmentReference.SequenceNumber); // UpdateFileRecord() expects the base segment to be present on disk byte[] redoData = fileRecordSegment.GetBytes(m_volume.BytesPerFileRecordSegment, m_volume.MinorVersion, false); ulong streamOffset = (ulong)(fileRecordSegment.SegmentNumber * m_volume.BytesPerFileRecordSegment); m_volume.LogClient.WriteLogRecord(m_mftRecord.BaseSegmentReference, m_mftRecord.DataRecord, streamOffset, NTFSLogOperation.InitializeFileRecordSegment, redoData, NTFSLogOperation.DeallocateFileRecordSegment, new byte[0], transactionID); UpdateFileRecordSegment(fileRecordSegment); fileRecordSegment.ReferenceCount = (ushort)fileNameRecords.Count; // Each FileNameRecord is about to be indexed fileRecordSegment.IsInUse = true; fileRecordSegment.IsDirectory = isDirectory; FileRecord fileRecord = new FileRecord(fileRecordSegment); StandardInformationRecord standardInformation = (StandardInformationRecord)fileRecord.CreateAttributeRecord(AttributeType.StandardInformation, String.Empty); standardInformation.CreationTime = fileNameRecords[0].CreationTime; standardInformation.ModificationTime = fileNameRecords[0].ModificationTime; standardInformation.MftModificationTime = fileNameRecords[0].MftModificationTime; standardInformation.LastAccessTime = fileNameRecords[0].LastAccessTime; standardInformation.FileAttributes = 0; foreach (FileNameRecord fileNameRecord in fileNameRecords) { FileNameAttributeRecord fileNameAttribute = (FileNameAttributeRecord)fileRecord.CreateAttributeRecord(AttributeType.FileName, String.Empty); fileNameAttribute.IsIndexed = true; fileNameAttribute.Record = fileNameRecord; } if (isDirectory) { string indexName = IndexHelper.GetIndexName(AttributeType.FileName); IndexRootRecord indexRoot = (IndexRootRecord)fileRecord.CreateAttributeRecord(AttributeType.IndexRoot, indexName); IndexHelper.InitializeIndexRoot(indexRoot, AttributeType.FileName, m_volume.BytesPerIndexRecord, m_volume.BytesPerCluster); } else { fileRecord.CreateAttributeRecord(AttributeType.Data, String.Empty); } UpdateFileRecord(fileRecord, transactionID); return(fileRecord); }
public void UpdateFileRecordSegment(FileRecordSegment recordSegment) { long segmentNumber = recordSegment.SegmentNumber; long firstSectorIndex = segmentNumber * m_volume.SectorsPerFileRecordSegment; if (segmentNumber >= FirstReservedSegmentNumber) { recordSegment.UpdateSequenceNumber++; } recordSegment.LogFileSequenceNumber = 0; byte[] recordSegmentBytes = recordSegment.GetBytes(m_volume.BytesPerFileRecordSegment, m_volume.MinorVersion); m_mftFile.Data.WriteSectors(firstSectorIndex, recordSegmentBytes); }
private static void WriteFileRecordSegment(byte[] mftData, FileRecordSegment segment, int bytesPerFileRecordSegment, byte minorNTFSVersion) { byte[] segmentBytes = segment.GetBytes(bytesPerFileRecordSegment, minorNTFSVersion, true); ByteWriter.WriteBytes(mftData, bytesPerFileRecordSegment * (int)segment.SegmentNumber, segmentBytes); }
public void UpdateFileRecord(FileRecord fileRecord, uint transactionID) { Dictionary <MftSegmentReference, byte[]> undoDictionary = new Dictionary <MftSegmentReference, byte[]>(); foreach (FileRecordSegment segment in fileRecord.Segments) { byte[] segmentBytes = segment.GetBytes(m_volume.BytesPerFileRecordSegment, m_volume.MinorVersion, false); undoDictionary.Add(segment.SegmentReference, segmentBytes); } AttributeRecord oldAttributeList = fileRecord.BaseSegment.GetImmediateAttributeRecord(AttributeType.AttributeList, String.Empty); fileRecord.UpdateSegments(m_volume.BytesPerFileRecordSegment, m_volume.MinorVersion); FileRecordSegment baseSegment = fileRecord.BaseSegment; for (int segmentIndex = 1; segmentIndex < fileRecord.Segments.Count; segmentIndex++) { FileRecordSegment segment = fileRecord.Segments[segmentIndex]; if (segment.SegmentReference == MftSegmentReference.NullReference) { // New segment, we must allocate space for it MftSegmentReference segmentReference; if (baseSegment.SegmentNumber == MasterFileTable.MasterFileTableSegmentNumber) { segmentReference = AllocateReservedFileRecordSegment(transactionID); } else { segmentReference = AllocateFileRecordSegment(transactionID); } FileRecordSegment newSegment = new FileRecordSegment(segmentReference.SegmentNumber, segmentReference.SequenceNumber, baseSegment.SegmentReference); newSegment.IsInUse = true; newSegment.IsDirectory = fileRecord.IsDirectory; newSegment.NextAttributeInstance = segment.NextAttributeInstance; newSegment.ImmediateAttributes.AddRange(segment.ImmediateAttributes); fileRecord.Segments[segmentIndex] = newSegment; } else if (segment.ImmediateAttributes.Count == 0) { byte[] undoData = undoDictionary[segment.SegmentReference]; ulong streamOffset = (ulong)(segment.SegmentNumber * m_volume.BytesPerFileRecordSegment); m_volume.LogClient.WriteLogRecord(m_mftRecord.BaseSegmentReference, m_mftRecord.DataRecord, streamOffset, m_volume.BytesPerFileRecordSegment, NTFSLogOperation.DeallocateFileRecordSegment, new byte[0], NTFSLogOperation.InitializeFileRecordSegment, undoData, transactionID); DeallocateFileRecordSegment(segment, transactionID); fileRecord.Segments.RemoveAt(segmentIndex); segmentIndex--; } } for (int segmentIndex = 1; segmentIndex < fileRecord.Segments.Count; segmentIndex++) { FileRecordSegment segment = fileRecord.Segments[segmentIndex]; byte[] undoData; byte[] redoData = segment.GetBytes(m_volume.BytesPerFileRecordSegment, m_volume.MinorVersion, false); ulong streamOffset = (ulong)(segment.SegmentNumber * m_volume.BytesPerFileRecordSegment); if (undoDictionary.TryGetValue(segment.SegmentReference, out undoData)) { m_volume.LogClient.WriteLogRecord(m_mftRecord.BaseSegmentReference, m_mftRecord.DataRecord, streamOffset, m_volume.BytesPerFileRecordSegment, NTFSLogOperation.InitializeFileRecordSegment, redoData, NTFSLogOperation.InitializeFileRecordSegment, undoData, transactionID); } else { // New segment m_volume.LogClient.WriteLogRecord(m_mftRecord.BaseSegmentReference, m_mftRecord.DataRecord, streamOffset, m_volume.BytesPerFileRecordSegment, NTFSLogOperation.InitializeFileRecordSegment, redoData, NTFSLogOperation.DeallocateFileRecordSegment, new byte[0], transactionID); } UpdateFileRecordSegment(segment); } if (oldAttributeList is NonResidentAttributeRecord) { new NonResidentAttributeData(m_volume, null, (NonResidentAttributeRecord)oldAttributeList).Truncate(0); } bool needsAttributeList = (fileRecord.Segments.Count > 1); if (needsAttributeList) { List <AttributeListEntry> entries = FileRecordHelper.BuildAttributeList(fileRecord.Segments, m_volume.BytesPerFileRecordSegment, m_volume.MinorVersion); int dataLength = AttributeList.GetLength(entries); int attributeListRecordLength = ResidentAttributeRecord.GetRecordLength(0, dataLength); int numberOfBytesFreeInBaseSegment = baseSegment.GetNumberOfBytesFree(m_volume.BytesPerFileRecordSegment, m_volume.MinorVersion); bool isResident = (attributeListRecordLength <= numberOfBytesFreeInBaseSegment); AttributeRecord attributeListRecord = baseSegment.CreateAttributeListRecord(isResident); AttributeList attributeList = new AttributeList(m_volume, attributeListRecord); attributeList.WriteEntries(entries); } byte[] baseRecordUndoData = undoDictionary[baseSegment.SegmentReference]; byte[] baseRecordRedoData = baseSegment.GetBytes(m_volume.BytesPerFileRecordSegment, m_volume.MinorVersion, false); ulong baseRecordStreamOffset = (ulong)(baseSegment.SegmentNumber * m_volume.BytesPerFileRecordSegment); m_volume.LogClient.WriteLogRecord(m_mftRecord.BaseSegmentReference, m_mftRecord.DataRecord, baseRecordStreamOffset, m_volume.BytesPerFileRecordSegment, NTFSLogOperation.InitializeFileRecordSegment, baseRecordRedoData, NTFSLogOperation.InitializeFileRecordSegment, baseRecordUndoData, transactionID); UpdateFileRecordSegment(baseSegment); }