示例#1
0
        /// <summary>
        /// Will remove the pointer while preserving the entry (if present)
        /// </summary>
        private void RemovePointerFromRoot(int indexOfEntryToRemove)
        {
            IndexEntry pointer = m_rootRecord.IndexEntries[indexOfEntryToRemove];

            if (pointer.IsLastEntry)
            {
                if (m_rootRecord.IndexEntries.Count == 1)
                {
                    m_rootRecord.IndexEntries.RemoveAt(indexOfEntryToRemove);
                    m_rootRecord.IsParentNode = false;
                }
                else
                {
                    MftSegmentReference fileReferenceToReinsert = m_rootRecord.IndexEntries[indexOfEntryToRemove - 1].FileReference;
                    byte[] keyToReinsert = m_rootRecord.IndexEntries[indexOfEntryToRemove - 1].Key;
                    m_rootRecord.IndexEntries.RemoveAt(indexOfEntryToRemove);
                    m_rootRecord.IndexEntries[indexOfEntryToRemove - 1].FileReference = MftSegmentReference.NullReference;
                    m_rootRecord.IndexEntries[indexOfEntryToRemove - 1].Key           = new byte[0];
                    AddEntry(fileReferenceToReinsert, keyToReinsert);
                }
            }
            else
            {
                MftSegmentReference fileReferenceToReinsert = pointer.FileReference;
                byte[] keyToReinsert = pointer.Key;
                m_rootRecord.IndexEntries.RemoveAt(indexOfEntryToRemove);
                AddEntry(fileReferenceToReinsert, keyToReinsert);
            }
            m_volume.UpdateFileRecord(m_fileRecord);
        }
示例#2
0
        public virtual void DeleteFile(FileRecord fileRecord)
        {
            MftSegmentReference parentDirectory       = fileRecord.ParentDirectoryReference;
            FileRecord          parentDirectoryRecord = GetFileRecord(parentDirectory);
            IndexData           parentDirectoryIndex  = new IndexData(this, parentDirectoryRecord, AttributeType.FileName);

            // Update parent directory index
            List <FileNameRecord> fileNameRecords = fileRecord.FileNameRecords;

            foreach (FileNameRecord fileNameRecord in fileNameRecords)
            {
                parentDirectoryIndex.RemoveEntry(fileNameRecord.GetBytes());
            }

            // Deallocate all data clusters
            foreach (AttributeRecord atttributeRecord in fileRecord.Attributes)
            {
                if (atttributeRecord is NonResidentAttributeRecord)
                {
                    NonResidentAttributeData attributeData = new NonResidentAttributeData(this, fileRecord, (NonResidentAttributeRecord)atttributeRecord);
                    attributeData.Truncate(0);
                }
            }

            m_mft.DeleteFile(fileRecord);
        }
        private FileRecord ReadMftRecord(bool useMftMirror, bool readMftMirror)
        {
            NTFSBootRecord    bootRecord       = m_volume.BootRecord;
            long              mftStartLCN      = useMftMirror ? (long)bootRecord.MftMirrorStartLCN : (long)bootRecord.MftStartLCN;
            long              mftSegmentNumber = readMftMirror ? MftMirrorSegmentNumber : MasterFileTableSegmentNumber;
            FileRecordSegment mftRecordSegment;

            try
            {
                mftRecordSegment = ReadMftRecordSegment(mftStartLCN, mftSegmentNumber);
            }
            catch (InvalidDataException)
            {
                throw new InvalidDataException("Invalid MFT base record segment");
            }

            if (!mftRecordSegment.IsBaseFileRecord)
            {
                throw new InvalidDataException("Invalid MFT file record, MFT segment number did not correspond to a base file record segment");
            }

            AttributeRecord attributeListRecord = mftRecordSegment.GetImmediateAttributeRecord(AttributeType.AttributeList, String.Empty);

            if (attributeListRecord == null)
            {
                return(new FileRecord(mftRecordSegment));
            }
            else
            {
                AttributeList              attributeList = new AttributeList(m_volume, attributeListRecord);
                List <AttributeListEntry>  entries       = attributeList.ReadEntries();
                List <MftSegmentReference> references    = AttributeList.GetSegmentReferenceList(entries);
                int baseSegmentIndex = MftSegmentReference.IndexOfSegmentNumber(references, MasterFileTableSegmentNumber);

                if (baseSegmentIndex >= 0)
                {
                    references.RemoveAt(baseSegmentIndex);
                }

                List <FileRecordSegment> recordSegments = new List <FileRecordSegment>();
                // we want the base record segment first
                recordSegments.Add(mftRecordSegment);

                foreach (MftSegmentReference reference in references)
                {
                    FileRecordSegment segment;
                    try
                    {
                        segment = ReadMftRecordSegment(mftStartLCN, reference);
                    }
                    catch (InvalidDataException)
                    {
                        throw new InvalidDataException("Invalid MFT file record, referenced segment is invalid");
                    }

                    recordSegments.Add(segment);
                }
                return(new FileRecord(recordSegments));
            }
        }
示例#4
0
 public NTFSRestartRecord(byte[] recordBytes)
 {
     MajorVersion             = LittleEndianConverter.ToUInt32(recordBytes, 0x00);
     MinorVersion             = LittleEndianConverter.ToUInt32(recordBytes, 0x04);
     StartOfCheckpointLsn     = LittleEndianConverter.ToUInt64(recordBytes, 0x08);
     OpenAttributeTableLsn    = LittleEndianConverter.ToUInt64(recordBytes, 0x10);
     AttributeNamesLsn        = LittleEndianConverter.ToUInt64(recordBytes, 0x18);
     DirtyPageTableLsn        = LittleEndianConverter.ToUInt64(recordBytes, 0x20);
     TransactionTableLsn      = LittleEndianConverter.ToUInt64(recordBytes, 0x28);
     OpenAttributeTableLength = LittleEndianConverter.ToUInt32(recordBytes, 0x30);
     AttributeNamesLength     = LittleEndianConverter.ToUInt32(recordBytes, 0x34);
     DirtyPageTableLength     = LittleEndianConverter.ToUInt32(recordBytes, 0x38);
     TransactionTableLength   = LittleEndianConverter.ToUInt32(recordBytes, 0x3C);
     if (recordBytes.Length >= LengthNTFS30)
     {
         Unknown1 = LittleEndianConverter.ToUInt64(recordBytes, 0x40);
         PreviousRestartRecordLsn = LittleEndianConverter.ToUInt64(recordBytes, 0x48);
         BytesPerCluster          = LittleEndianConverter.ToUInt32(recordBytes, 0x50);
         UsnJournal = new MftSegmentReference(recordBytes, 0x58);
         Unknown2   = LittleEndianConverter.ToUInt64(recordBytes, 0x60);
         if (recordBytes.Length >= LengthVista)
         {
             UnknownLsn = LittleEndianConverter.ToUInt64(recordBytes, 0x68);
         }
     }
 }
示例#5
0
        /// <returns>Index in open attribute table</returns>
        private int AddToOpenAttributeTable(MftSegmentReference fileReference, AttributeType attributeType, string attributeName, ulong lsnOfOpenRecord)
        {
            int openAttributeIndex = m_openAttributes.Count;

            m_openAttributes.Add(new OpenAttribute(fileReference, attributeType, attributeName, lsnOfOpenRecord));
            return(openAttributeIndex);
        }
示例#6
0
        public OpenAttributeEntry(byte[] buffer, int offset, uint majorVersion)
        {
            m_majorVersion = majorVersion;

            int fileReferenceOffset       = (m_majorVersion == 0) ? FileReferenceOffsetV0 : FileReferenceOffsetV1;
            int lsnOfOpenRecordOffset     = (m_majorVersion == 0) ? LsnOfOpenRecordOffsetV0 : LsnOfOpenRecordOffsetV1;
            int dirtyPagesSeenOffset      = (m_majorVersion == 0) ? DirtyPagesSeenOffsetV0 : DirtyPagesSeenOffsetV1;
            int attributeTypeCodeOffset   = (m_majorVersion == 0) ? AttributeTypeCodeOffsetV0 : AttributeTypeCodeOffsetV1;
            int bytesPerIndexBufferOffset = (m_majorVersion == 0) ? BytesPerIndexBufferOffsetV0 : BytesPerIndexBufferOffsetV1;

            AllocatedOrNextFree = LittleEndianConverter.ToUInt32(buffer, offset + 0x00);
            if (majorVersion == 0)
            {
                AttributeOffset = LittleEndianConverter.ToUInt32(buffer, offset + 0x04);
            }
            FileReference   = new MftSegmentReference(buffer, offset + fileReferenceOffset);
            LsnOfOpenRecord = LittleEndianConverter.ToUInt64(buffer, offset + lsnOfOpenRecordOffset);
            DirtyPagesSeen  = Convert.ToBoolean(ByteReader.ReadByte(buffer, offset + dirtyPagesSeenOffset));
            if (m_majorVersion == 0)
            {
                // This field exists in NTFS v1.2, will be false in NTFS v3.0+
                AttributeNamePresent = Convert.ToBoolean(ByteReader.ReadByte(buffer, offset + 0x19));
            }
            AttributeTypeCode      = (AttributeType)LittleEndianConverter.ToUInt32(buffer, offset + attributeTypeCodeOffset);
            PointerToAttributeName = LittleEndianConverter.ToUInt64(buffer, offset + 0x20);

            if (AttributeTypeCode == AttributeType.IndexAllocation)
            {
                BytesPerIndexBuffer = LittleEndianConverter.ToUInt32(buffer, offset + bytesPerIndexBufferOffset);
            }
        }
示例#7
0
 protected internal virtual FileRecord GetFileRecord(MftSegmentReference fileReference)
 {
     lock (m_mftLock)
     {
         return(m_mft.GetFileRecord(fileReference));
     }
 }
示例#8
0
        public virtual FileRecord CreateFile(MftSegmentReference parentDirectory, string fileName, bool isDirectory)
        {
            // Worst case scenrario: the MFT might be full and the parent directory index requires multiple splits
            if (NumberOfFreeClusters < 24)
            {
                throw new DiskFullException();
            }
            FileRecord parentDirectoryRecord = GetFileRecord(parentDirectory);

            m_mftLock.AcquireWriterLock(Timeout.Infinite);
            IndexData parentDirectoryIndex = new IndexData(this, parentDirectoryRecord, AttributeType.FileName);

            if (parentDirectoryIndex.ContainsFileName(fileName))
            {
                m_mftLock.ReleaseWriterLock();
                throw new AlreadyExistsException();
            }

            List <FileNameRecord> fileNameRecords = IndexHelper.GenerateFileNameRecords(parentDirectory, fileName, isDirectory, m_generateDosNames, parentDirectoryIndex);
            uint       transactionID = m_logClient.AllocateTransactionID();
            FileRecord fileRecord    = m_mft.CreateFile(fileNameRecords, transactionID);

            // Update parent directory index
            foreach (FileNameRecord fileNameRecord in fileNameRecords)
            {
                parentDirectoryIndex.AddEntry(fileRecord.BaseSegmentReference, fileNameRecord.GetBytes());
            }
            m_logClient.WriteForgetTransactionRecord(transactionID);
            m_logClient.WriteRestartRecord(this.MajorVersion, true);
            m_mftLock.ReleaseWriterLock();

            return(fileRecord);
        }
示例#9
0
        public virtual void DeleteFile(FileRecord fileRecord)
        {
            MftSegmentReference parentDirectory       = fileRecord.ParentDirectoryReference;
            FileRecord          parentDirectoryRecord = GetFileRecord(parentDirectory);

            m_mftLock.AcquireWriterLock(Timeout.Infinite);
            IndexData parentDirectoryIndex = new IndexData(this, parentDirectoryRecord, AttributeType.FileName);

            uint transactionID = m_logClient.AllocateTransactionID();
            // Update parent directory index
            List <FileNameRecord> fileNameRecords = fileRecord.FileNameRecords;

            foreach (FileNameRecord fileNameRecord in fileNameRecords)
            {
                parentDirectoryIndex.RemoveEntry(fileNameRecord.GetBytes());
            }

            // Deallocate all data clusters
            foreach (AttributeRecord atttributeRecord in fileRecord.Attributes)
            {
                if (atttributeRecord is NonResidentAttributeRecord)
                {
                    NonResidentAttributeData attributeData = new NonResidentAttributeData(this, fileRecord, (NonResidentAttributeRecord)atttributeRecord);
                    attributeData.Truncate(0);
                }
            }

            m_mft.DeleteFile(fileRecord, transactionID);
            m_logClient.WriteForgetTransactionRecord(transactionID);
            m_logClient.WriteRestartRecord(this.MajorVersion, true);
            m_mftLock.ReleaseWriterLock();
        }
示例#10
0
 public void WriteRestartRecord(ushort majorNTFSVersion, bool isClean)
 {
     NTFSRestartRecord   previousRestartRecord = ReadCurrentRestartRecord();
     MftSegmentReference usnJournal            = previousRestartRecord.UsnJournal;
     ulong     previousRestartRecordLsn        = previousRestartRecord.PreviousRestartRecordLsn;
     LfsRecord restartRecord = WriteRestartRecord(previousRestartRecordLsn, usnJournal, majorNTFSVersion, isClean);
 }
示例#11
0
            public List <uint> AssociatedTransactions = new List <uint>(); // List of transactions using this open attribute

            public OpenAttribute(MftSegmentReference fileReference, AttributeType attributeType, string attributeName, ulong lsnOfOpenRecord)
            {
                FileReference   = fileReference;
                AttributeType   = attributeType;
                AttributeName   = attributeName;
                LsnOfOpenRecord = lsnOfOpenRecord;
            }
示例#12
0
        public virtual FileRecord CreateFile(MftSegmentReference parentDirectory, string fileName, bool isDirectory)
        {
            // Worst case scenrario: the MFT might be full and the parent directory index requires multiple splits
            if (NumberOfFreeClusters < 24)
            {
                throw new DiskFullException();
            }
            FileRecord parentDirectoryRecord = GetFileRecord(parentDirectory);
            IndexData  parentDirectoryIndex  = new IndexData(this, parentDirectoryRecord, AttributeType.FileName);

            if (parentDirectoryIndex.ContainsFileName(fileName))
            {
                throw new AlreadyExistsException();
            }

            List <FileNameRecord> fileNameRecords = IndexHelper.GenerateFileNameRecords(parentDirectory, fileName, isDirectory, m_generateDosNames, parentDirectoryIndex);
            FileRecord            fileRecord      = m_mft.CreateFile(fileNameRecords);

            // Update parent directory index
            foreach (FileNameRecord fileNameRecord in fileNameRecords)
            {
                parentDirectoryIndex.AddEntry(fileRecord.BaseSegmentReference, fileNameRecord.GetBytes());
            }

            return(fileRecord);
        }
示例#13
0
 public void WriteRestartRecord(bool isClean)
 {
     ulong usnJournalUnknown1       = m_currentRestartRecord.UsnJournalUnknown1;
     ulong previousRestartRecordLsn = m_currentRestartRecord.PreviousRestartRecordLsn;
     MftSegmentReference usnJournal = m_currentRestartRecord.UsnJournal;
     ulong     usnJournalUnknown2   = m_currentRestartRecord.UsnJournalUnknown2;
     LfsRecord restartRecord        = WriteRestartRecord(usnJournalUnknown1, previousRestartRecordLsn, usnJournal, usnJournalUnknown2, isClean);
 }
示例#14
0
        protected internal virtual FileRecord GetFileRecord(MftSegmentReference fileReference)
        {
            m_mftLock.AcquireReaderLock(Timeout.Infinite);
            FileRecord fileRecord = m_mft.GetFileRecord(fileReference);

            m_mftLock.ReleaseReaderLock();
            return(fileRecord);
        }
示例#15
0
        private LfsRecord WriteRestartRecord(ulong previousRestartRecordLsn, MftSegmentReference usnJournal, ushort majorNTFSVersion, bool isClean)
        {
            NTFSRestartRecord restartRecord = new NTFSRestartRecord(m_majorVersion, m_minorVersion);

            restartRecord.StartOfCheckpointLsn     = m_lastClientLsn;
            restartRecord.PreviousRestartRecordLsn = previousRestartRecordLsn;
            if (isClean)
            {
                if (m_transactions.Count > 0)
                {
                    throw new InvalidOperationException("All TransactionIDs must be deallocated before writing a clean restart record");
                }
            }
            else if (m_openAttributes.Count > 0)
            {
                byte[] attributeNameTableBytes;
                byte[] openAttributeTableBytes = GetOpenAttributeTableBytes(out attributeNameTableBytes);
                m_lastClientLsn = 0;
                uint      transactionID            = AllocateTransactionID(); // These records must have a valid transactionID
                LfsRecord openAttributeTableRecord = WriteLogRecord(null, null, 0, NTFSLogOperation.OpenAttributeTableDump, openAttributeTableBytes, NTFSLogOperation.Noop, new byte[0], transactionID);
                restartRecord.OpenAttributeTableLsn    = openAttributeTableRecord.ThisLsn;
                restartRecord.OpenAttributeTableLength = (uint)openAttributeTableBytes.Length;
                if (attributeNameTableBytes != null)
                {
                    LfsRecord attributeNameTableRecord = WriteLogRecord(null, null, 0, NTFSLogOperation.AttributeNamesDump, openAttributeTableBytes, NTFSLogOperation.Noop, new byte[0], transactionID);
                    restartRecord.AttributeNamesLsn    = attributeNameTableRecord.ThisLsn;
                    restartRecord.AttributeNamesLength = (uint)attributeNameTableBytes.Length;
                }
                DeallocateTransactionID(transactionID);
            }
            restartRecord.BytesPerCluster = (uint)Volume.BytesPerCluster;
            restartRecord.UsnJournal      = usnJournal;
            byte[]    clientData = restartRecord.GetBytes(majorNTFSVersion);
            LfsRecord result     = m_logFile.WriteRecord(m_clientIndex, LfsRecordType.ClientRestart, 0, 0, 0, clientData);

            m_lastClientLsn = result.ThisLsn;
            LfsClientRecord clientRecord = m_logFile.GetClientRecord(m_clientIndex);

            if (isClean)
            {
                clientRecord.OldestLsn = restartRecord.StartOfCheckpointLsn;
            }
            else
            {
                ulong oldestLsn = restartRecord.StartOfCheckpointLsn;
                foreach (Transaction transaction in m_transactions)
                {
                    if (transaction.OldestLsn != 0 && transaction.OldestLsn < oldestLsn)
                    {
                        oldestLsn = transaction.OldestLsn;
                    }
                }
                clientRecord.OldestLsn = oldestLsn;
            }
            clientRecord.ClientRestartLsn = result.ThisLsn;
            m_logFile.WriteRestartPage(isClean);
            return(result);
        }
示例#16
0
        public virtual void MoveFile(FileRecord fileRecord, MftSegmentReference newParentDirectory, string newFileName)
        {
            // Worst case scenrario: the new parent directory index requires multiple splits
            if (NumberOfFreeClusters < 4)
            {
                throw new DiskFullException();
            }

            FileRecord oldParentDirectoryRecord = GetFileRecord(fileRecord.ParentDirectoryReference);
            IndexData  oldParentDirectoryIndex  = new IndexData(this, oldParentDirectoryRecord, AttributeType.FileName);
            IndexData  newParentDirectoryIndex;

            if (fileRecord.ParentDirectoryReference == newParentDirectory)
            {
                newParentDirectoryIndex = oldParentDirectoryIndex;
            }
            else
            {
                FileRecord newParentDirectoryRecord = GetFileRecord(newParentDirectory);
                newParentDirectoryIndex = new IndexData(this, newParentDirectoryRecord, AttributeType.FileName);
                if (newParentDirectoryIndex.ContainsFileName(newFileName))
                {
                    throw new AlreadyExistsException();
                }
            }

            List <FileNameRecord> fileNameRecords = fileRecord.FileNameRecords;

            foreach (FileNameRecord fileNameRecord in fileNameRecords)
            {
                oldParentDirectoryIndex.RemoveEntry(fileNameRecord.GetBytes());
            }

            DateTime       creationTime        = fileRecord.FileNameRecord.CreationTime;
            DateTime       modificationTime    = fileRecord.FileNameRecord.ModificationTime;
            DateTime       mftModificationTime = fileRecord.FileNameRecord.MftModificationTime;
            DateTime       lastAccessTime      = fileRecord.FileNameRecord.LastAccessTime;
            ulong          allocatedLength     = fileRecord.FileNameRecord.AllocatedLength;
            ulong          fileSize            = fileRecord.FileNameRecord.FileSize;
            FileAttributes fileAttributes      = fileRecord.FileNameRecord.FileAttributes;
            ushort         packedEASize        = fileRecord.FileNameRecord.PackedEASize;

            fileNameRecords = IndexHelper.GenerateFileNameRecords(newParentDirectory, newFileName, fileRecord.IsDirectory, m_generateDosNames, newParentDirectoryIndex, creationTime, modificationTime, mftModificationTime, lastAccessTime, allocatedLength, fileSize, fileAttributes, packedEASize);
            fileRecord.RemoveAttributeRecords(AttributeType.FileName, String.Empty);
            foreach (FileNameRecord fileNameRecord in fileNameRecords)
            {
                FileNameAttributeRecord fileNameAttribute = (FileNameAttributeRecord)fileRecord.CreateAttributeRecord(AttributeType.FileName, String.Empty);
                fileNameAttribute.IsIndexed = true;
                fileNameAttribute.Record    = fileNameRecord;
            }
            UpdateFileRecord(fileRecord);

            foreach (FileNameRecord fileNameRecord in fileNameRecords)
            {
                newParentDirectoryIndex.AddEntry(fileRecord.BaseSegmentReference, fileNameRecord.GetBytes());
            }
        }
示例#17
0
        public virtual FileRecord GetFileRecord(string path)
        {
            if (path != String.Empty && !path.StartsWith(@"\"))
            {
                throw new InvalidPathException(String.Format("The path '{0}' is invalid", path));
            }

            if (path.EndsWith(@"\"))
            {
                path = path.Substring(0, path.Length - 1);
            }

            if (path == String.Empty)
            {
                return(GetFileRecord(MasterFileTable.RootDirSegmentReference));
            }

            string[]            components         = path.Substring(1).Split('\\');
            MftSegmentReference directoryReference = MasterFileTable.RootDirSegmentReference;

            lock (m_mftLock)
            {
                for (int index = 0; index < components.Length; index++)
                {
                    FileRecord directoryRecord = GetFileRecord(directoryReference);
                    if (index < components.Length - 1)
                    {
                        if (!directoryRecord.IsDirectory)
                        {
                            throw new InvalidPathException(String.Format("The path '{0}' is invalid", path));
                        }
                        IndexData indexData = new IndexData(this, directoryRecord, AttributeType.FileName);
                        directoryReference = indexData.FindFileNameRecordSegmentReference(components[index]);
                        if (directoryReference == null)
                        {
                            throw new DirectoryNotFoundException(String.Format("Could not find part of the path '{0}'", path));
                        }
                    }
                    else // Last component
                    {
                        IndexData           indexData     = new IndexData(this, directoryRecord, AttributeType.FileName);
                        MftSegmentReference fileReference = indexData.FindFileNameRecordSegmentReference(components[index]);
                        if (fileReference == null)
                        {
                            throw new FileNotFoundException(String.Format("Could not find file '{0}'", path));
                        }
                        FileRecord fileRecord = GetFileRecord(fileReference);
                        if (!fileRecord.IsMetaFile)
                        {
                            return(fileRecord);
                        }
                    }
                }
            }
            // We should never get here
            throw new InvalidPathException();
        }
示例#18
0
 public override bool Equals(object obj)
 {
     if (obj is MftSegmentReference)
     {
         MftSegmentReference reference = (MftSegmentReference)obj;
         return((SegmentNumber == reference.SegmentNumber) && (SequenceNumber == reference.SequenceNumber));
     }
     return(false);
 }
示例#19
0
        private FileRecord ReadMftRecord(bool useMftMirror, bool readMftMirror)
        {
            NTFSBootRecord bootRecord = m_volume.BootRecord;

            if (bootRecord != null)
            {
                long mftStartLCN      = useMftMirror ? (long)bootRecord.MftMirrorStartLCN : (long)bootRecord.MftStartLCN;
                long mftSegmentNumber = readMftMirror ? MftMirrorSegmentNumber : MasterFileTableSegmentNumber;
                FileRecordSegment mftRecordSegment = ReadFileRecordSegment(mftStartLCN, mftSegmentNumber);
                if (!mftRecordSegment.IsBaseFileRecord)
                {
                    throw new InvalidDataException("Invalid MFT record, not a base record");
                }

                AttributeRecord attributeListRecord = mftRecordSegment.GetImmediateAttributeRecord(AttributeType.AttributeList, String.Empty);
                if (attributeListRecord == null)
                {
                    return(new FileRecord(mftRecordSegment));
                }
                else
                {
                    // I have never personally seen an MFT with an attribute list
                    AttributeList              attributeList = new AttributeList(m_volume, attributeListRecord);
                    List <AttributeListEntry>  entries       = attributeList.ReadEntries();
                    List <MftSegmentReference> references    = AttributeList.GetSegmentReferenceList(entries);
                    int baseSegmentIndex = MftSegmentReference.IndexOfSegmentNumber(references, MasterFileTableSegmentNumber);

                    if (baseSegmentIndex >= 0)
                    {
                        references.RemoveAt(baseSegmentIndex);
                    }

                    List <FileRecordSegment> recordSegments = new List <FileRecordSegment>();
                    // we want the base record segment first
                    recordSegments.Add(mftRecordSegment);

                    foreach (MftSegmentReference reference in references)
                    {
                        FileRecordSegment segment = ReadFileRecordSegment(mftStartLCN, reference);
                        if (segment != null)
                        {
                            recordSegments.Add(segment);
                        }
                        else
                        {
                            throw new InvalidDataException("Invalid MFT record, missing segment");
                        }
                    }
                    return(new FileRecord(recordSegments));
                }
            }
            else
            {
                return(null);
            }
        }
示例#20
0
 public FileNameRecord(MftSegmentReference parentDirectory, string fileName, bool isDirectory, DateTime creationTime)
 {
     ParentDirectory     = parentDirectory;
     CreationTime        = creationTime;
     ModificationTime    = creationTime;
     MftModificationTime = creationTime;
     LastAccessTime      = creationTime;
     IsDirectory         = isDirectory;
     FileName            = fileName;
 }
        public FileRecord GetFileRecord(MftSegmentReference fileReference)
        {
            FileRecord fileRecord = GetFileRecord(fileReference.SegmentNumber);

            if (fileRecord.BaseSequenceNumber != fileReference.SequenceNumber)
            {
                // The file record segment has been freed and reallocated, and an obsolete version is being requested
                throw new InvalidDataException("MftSegmentReference SequenceNumber does not match BaseFileRecordSegment");
            }
            return(fileRecord);
        }
        public FileRecordSegment GetFileRecordSegment(MftSegmentReference reference)
        {
            FileRecordSegment result = GetFileRecordSegment(reference.SegmentNumber);

            if (result.SequenceNumber != reference.SequenceNumber)
            {
                // The file record segment has been modified, and an older version has been requested
                throw new InvalidDataException("MftSegmentReference SequenceNumber does not match FileRecordSegment");
            }
            return(result);
        }
示例#23
0
        public virtual FileRecord GetFileRecord(string path)
        {
            if (path != String.Empty && !path.StartsWith(@"\"))
            {
                throw new ArgumentException("Invalid path");
            }

            if (path.EndsWith(@"\"))
            {
                path = path.Substring(0, path.Length - 1);
            }

            if (path == String.Empty)
            {
                return(GetFileRecord(MasterFileTable.RootDirSegmentReference));
            }

            string[]            components         = path.Substring(1).Split('\\');
            MftSegmentReference directoryReference = MasterFileTable.RootDirSegmentReference;

            for (int index = 0; index < components.Length; index++)
            {
                FileRecord directoryRecord = GetFileRecord(directoryReference);
                if (index < components.Length - 1)
                {
                    if (!directoryRecord.IsDirectory)
                    {
                        return(null);
                    }
                    IndexData indexData = new IndexData(this, directoryRecord, AttributeType.FileName);
                    directoryReference = indexData.FindFileNameRecordSegmentReference(components[index]);
                    if (directoryReference == null)
                    {
                        return(null);
                    }
                }
                else // Last component
                {
                    IndexData           indexData     = new IndexData(this, directoryRecord, AttributeType.FileName);
                    MftSegmentReference fileReference = indexData.FindFileNameRecordSegmentReference(components[index]);
                    if (fileReference == null)
                    {
                        return(null);
                    }
                    FileRecord fileRecord = GetFileRecord(fileReference);
                    if (fileRecord != null && !fileRecord.IsMetaFile)
                    {
                        return(fileRecord);
                    }
                }
            }

            return(null);
        }
示例#24
0
        public FileRecordSegment GetFileRecordSegment(MftSegmentReference reference)
        {
            FileRecordSegment result = GetFileRecordSegment(reference.SegmentNumber);

            if (result.SequenceNumber != reference.SequenceNumber)
            {
                // The file record segment has been modified, and an older version has been requested
                return(null);
            }
            return(result);
        }
示例#25
0
        private FileRecordSegment ReadFileRecordSegment(long mftStartLCN, MftSegmentReference reference)
        {
            FileRecordSegment result = ReadFileRecordSegment(mftStartLCN, reference.SegmentNumber);

            if (result.SequenceNumber != reference.SequenceNumber)
            {
                // The file record segment has been freed and reallocated, and an obsolete version is being requested
                return(null);
            }
            return(result);
        }
        private FileRecordSegment ReadMftRecordSegment(long mftStartLCN, MftSegmentReference reference)
        {
            FileRecordSegment result = ReadMftRecordSegment(mftStartLCN, reference.SegmentNumber);

            if (result.SequenceNumber != reference.SequenceNumber)
            {
                // The file record segment has been freed and reallocated, and an obsolete version is being requested
                throw new InvalidDataException("MftSegmentReference SequenceNumber does not match FileRecordSegment");
            }
            return(result);
        }
示例#27
0
        public FileNameIndexEntry(byte[] buffer, int offset)
        {
            FileReference = new MftSegmentReference(buffer, offset + 0x00);
            RecordLength = LittleEndianConverter.ToUInt16(buffer, offset + 0x08);
            FileNameOffset = LittleEndianConverter.ToUInt16(buffer, offset + 0x0A);
            IndexFlags = (IndexEntryFlags)LittleEndianConverter.ToUInt16(buffer, offset + 0x0C);

            if (RecordLength > 16)// otherwise it's the last record
            {
                Record = new FileNameRecord(buffer, offset + 0x10);
            }
        }
示例#28
0
 internal void UpdateDirectoryIndex(MftSegmentReference parentDirectory, List <FileNameRecord> fileNameRecords)
 {
     lock (m_mftLock)
     {
         FileRecord parentDirectoryRecord = GetFileRecord(parentDirectory);
         IndexData  parentDirectoryIndex  = new IndexData(this, parentDirectoryRecord, AttributeType.FileName);
         foreach (FileNameRecord fileNameRecord in fileNameRecords)
         {
             parentDirectoryIndex.UpdateFileNameRecord(fileNameRecord);
         }
     }
 }
示例#29
0
        public LfsRecord WriteLogRecord(MftSegmentReference fileReference, AttributeRecord attributeRecord, ulong streamOffset, int structureLength, int recordOffset, int attributeOffset, NTFSLogOperation redoOperation, byte[] redoData, NTFSLogOperation undoOperation, byte[] undoData, uint transactionID, bool flushToDisk)
        {
            int openAttributeOffset = 0;

            if (fileReference != null)
            {
                int openAttributeIndex = IndexOfOpenAttribute(fileReference, attributeRecord.AttributeType, attributeRecord.Name);
                if (openAttributeIndex == -1)
                {
                    openAttributeIndex = AddToOpenAttributeTable(fileReference, attributeRecord.AttributeType, attributeRecord.Name, m_lastClientLsn);
                    m_openAttributes[openAttributeIndex].AssociatedTransactions.Add(transactionID);
                    openAttributeOffset = OpenAttributeIndexToOffset(openAttributeIndex);
                    OpenAttributeEntry entry = new OpenAttributeEntry(m_majorVersion);
                    entry.AllocatedOrNextFree = RestartTableEntry.RestartEntryAllocated;
                    // Note: NTFS v5.1 driver calulates AttributeOffset using entry length of 0x28, the reason is unclear but we're immitating this.
                    entry.AttributeOffset   = (uint)(RestartTableHeader.Length + openAttributeIndex * OpenAttributeEntry.LengthV1);
                    entry.FileReference     = fileReference;
                    entry.LsnOfOpenRecord   = m_lastClientLsn;
                    entry.AttributeTypeCode = attributeRecord.AttributeType;
                    if (attributeRecord.AttributeType == AttributeType.IndexAllocation)
                    {
                        entry.BytesPerIndexBuffer = (uint)Volume.BytesPerIndexRecord;
                    }
                    byte[]    openAttributeBytes  = entry.GetBytes();
                    byte[]    attributeNameBytes  = System.Text.Encoding.Unicode.GetBytes(attributeRecord.Name);
                    LfsRecord openAttributeRecord = WriteLogRecord(openAttributeOffset, 0, 0, 0, new List <long>(), NTFSLogOperation.OpenNonResidentAttribute, openAttributeBytes, NTFSLogOperation.Noop, attributeNameBytes, transactionID, false);
                }
                else
                {
                    openAttributeOffset = OpenAttributeIndexToOffset(openAttributeIndex);
                    if (!m_openAttributes[openAttributeIndex].AssociatedTransactions.Contains(transactionID))
                    {
                        m_openAttributes[openAttributeIndex].AssociatedTransactions.Add(transactionID);
                    }
                }
            }

            List <long> lcnList = new List <long>();

            if (attributeRecord is NonResidentAttributeRecord)
            {
                long startVCN     = (long)(streamOffset / (uint)Volume.BytesPerCluster);
                int  clusterCount = (int)Math.Ceiling((double)structureLength / Volume.BytesPerCluster);
                for (long vcn = startVCN; vcn < startVCN + clusterCount; vcn++)
                {
                    long lcn = ((NonResidentAttributeRecord)attributeRecord).DataRunSequence.GetDataClusterLCN(vcn);
                    lcnList.Add(lcn);
                }
            }

            return(WriteLogRecord(openAttributeOffset, streamOffset, recordOffset, attributeOffset, lcnList, redoOperation, redoData, undoOperation, undoData, transactionID, flushToDisk));
        }
示例#30
0
 private int IndexOfOpenAttribute(MftSegmentReference fileReference, AttributeType attributeType, string attributeName)
 {
     for (int index = 0; index < m_openAttributes.Count; index++)
     {
         if (m_openAttributes[index].FileReference == fileReference &&
             m_openAttributes[index].AttributeType == attributeType &&
             String.Equals(m_openAttributes[index].AttributeName, attributeName, StringComparison.OrdinalIgnoreCase))
         {
             return(index);
         }
     }
     return(-1);
 }