public List <TransactionEntry> ReadTransactionTable(NTFSRestartRecord restartRecord) { ulong transactionTableLsn = restartRecord.TransactionTableLsn; if (transactionTableLsn != 0) { NTFSLogRecord record = ReadLogRecord(transactionTableLsn); if (record.RedoOperation != NTFSLogOperation.TransactionTableDump) { string message = String.Format("Restart record TransactionTableLsn points to a record with RedoOperation {0}", record.RedoOperation); throw new InvalidDataException(message); } if (restartRecord.TransactionTableLength != record.RedoData.Length) { throw new InvalidDataException("Transcation table length does not match restart record"); } return(RestartTableHelper.ReadTable <TransactionEntry>(record.RedoData, restartRecord.MajorVersion)); } else { return(null); } }
public List <AttributeNameEntry> ReadAttributeNamesTable(NTFSRestartRecord restartRecord) { ulong attributeNamesLsn = restartRecord.AttributeNamesLsn; if (attributeNamesLsn != 0) { NTFSLogRecord record = ReadLogRecord(attributeNamesLsn); if (record.RedoOperation != NTFSLogOperation.AttributeNamesDump) { string message = String.Format("Restart record AttributeNamesLsn points to a record with RedoOperation {0}", record.RedoOperation); throw new InvalidDataException(message); } if (restartRecord.AttributeNamesLength != record.RedoData.Length) { throw new InvalidDataException("Open attribute table length does not match restart record"); } return(AttributeNameEntry.ReadTable(record.RedoData)); } else { return(null); } }
private LfsRecord WriteLogRecord(NTFSLogRecord ntfsLogRecord, uint transactionID, bool flushToDisk) { LfsClientRecord clientRecord = m_logFile.GetClientRecord(m_clientIndex); byte[] clientData = ntfsLogRecord.GetBytes(); int transactionIndex = IndexOfTransaction(transactionID); ulong lastLsnToUndo = m_transactions[transactionIndex].LastLsnToUndo; LfsRecord result = m_logFile.WriteRecord(m_clientIndex, LfsRecordType.ClientRecord, m_lastClientLsn, lastLsnToUndo, transactionID, clientData, flushToDisk); m_lastClientLsn = result.ThisLsn; m_transactions[transactionIndex].LastLsnToUndo = result.ThisLsn; if (m_transactions[transactionIndex].OldestLsn == 0) { m_transactions[transactionIndex].OldestLsn = result.ThisLsn; } return(result); }
private LfsRecord WriteLogRecord(int openAttributeOffset, ulong streamOffset, int recordOffset, int attributeOffset, List <long> lcnList, NTFSLogOperation redoOperation, byte[] redoData, NTFSLogOperation undoOperation, byte[] undoData, uint transactionID, bool flushToDisk) { NTFSLogRecord ntfsLogRecord = new NTFSLogRecord(); ntfsLogRecord.TargetAttributeOffset = (ushort)openAttributeOffset; ntfsLogRecord.RedoOperation = redoOperation; ntfsLogRecord.RedoData = redoData; ntfsLogRecord.UndoOperation = undoOperation; ntfsLogRecord.UndoData = undoData; ntfsLogRecord.TargetVCN = (long)(streamOffset / (uint)Volume.BytesPerCluster); ntfsLogRecord.LCNsForPage.AddRange(lcnList); int offsetInCluster = (int)(streamOffset % (uint)Volume.BytesPerCluster); ntfsLogRecord.RecordOffset = (ushort)recordOffset; ntfsLogRecord.AttributeOffset = (ushort)attributeOffset; ntfsLogRecord.ClusterBlockOffset = (ushort)(offsetInCluster / NTFSLogRecord.BytesPerLogBlock); return(WriteLogRecord(ntfsLogRecord, transactionID, flushToDisk)); }
public LfsRecord WriteForgetTransactionRecord(uint transactionID, bool flushToDisk) { NTFSLogRecord ntfsLogRecord = new NTFSLogRecord(); ntfsLogRecord.RedoOperation = NTFSLogOperation.ForgetTransaction; ntfsLogRecord.UndoOperation = NTFSLogOperation.CompensationLogRecord; LfsRecord result = WriteLogRecord(ntfsLogRecord, transactionID, flushToDisk); DeallocateTransactionID(transactionID); // Update the open attribute table and remove any open attribute that no longer has an associated transaction for (int index = 0; index < m_openAttributes.Count; index++) { OpenAttribute openAttribute = m_openAttributes[index]; openAttribute.AssociatedTransactions.Remove(transactionID); if (openAttribute.AssociatedTransactions.Count == 0) { m_openAttributes.RemoveAt(index); index--; } } return(result); }
public List <NTFSLogRecord> FindRecordsToRedo() { NTFSRestartRecord restartRecord = ReadCurrentRestartRecord(); List <DirtyPageEntry> dirtyPageTable = ReadDirtyPageTable(restartRecord); ulong redoLsn = FindRedoLsn(dirtyPageTable); LfsRecord firstRecord = m_logFile.ReadRecord(redoLsn); List <LfsRecord> records = m_logFile.FindNextRecords(redoLsn, m_clientIndex); records.Insert(0, firstRecord); List <NTFSLogRecord> result = new List <NTFSLogRecord>(); foreach (LfsRecord record in records) { if (record.RecordType == LfsRecordType.ClientRecord) { NTFSLogRecord clientRecord = new NTFSLogRecord(record.Data); switch (clientRecord.RedoOperation) { case NTFSLogOperation.Noop: case NTFSLogOperation.OpenAttributeTableDump: case NTFSLogOperation.AttributeNamesDump: case NTFSLogOperation.DirtyPageTableDump: case NTFSLogOperation.TransactionTableDump: { continue; } default: { result.Add(clientRecord); break; } } } } return(result); }