private void LoadData(MFTLoadDepth loadDepth = MFTLoadDepth.Full) { if (loadDepth.CompareTo(_dataLoaded) <= 0) { // If we're not loading more than we already have, just stop here. return; } string Magic = Encoding.ASCII.GetString(_data, 0, 4); if (!Magic.Equals("FILE")) { Console.Error.WriteLine("Warning: MFT record number {0} was missing the 'FILE' header. Skipping.", RecordNum); // This record is invalid, so don't read any more. Valid = false; return; } ushort updateSequenceOffset = BitConverter.ToUInt16(_data, 4); ushort updateSequenceLength = BitConverter.ToUInt16(_data, 6); ushort updateSequenceNumber = BitConverter.ToUInt16(_data, updateSequenceOffset); ushort[] updateSequenceArray = new ushort[updateSequenceLength - 1]; ushort read = 1; while (read < updateSequenceLength) { updateSequenceArray[read - 1] = BitConverter.ToUInt16(_data, (ushort)(updateSequenceOffset + read * 2)); read++; } // Apply fixups to the in-memory array try { FixupStream.FixArray(_data, updateSequenceNumber, updateSequenceArray, (int)BytesPerSector); } catch (NTFSFixupException e) { Console.Error.WriteLine(e); // This record is invalid, so don't read any more. Valid = false; return; } LoadHeader(); LoadAttributes(AttributeOffset, loadDepth); if (_attributes.Count == 0) { Console.Error.WriteLine("Warning: MFT record number {0} had no attributes.", RecordNum); } _dataLoaded = loadDepth; // If we've loaded everything, dispose of the underlying byte array. if (_dataLoaded == MFTLoadDepth.Full) { _data = null; } }
private MFTRecord(ulong recordNum, FileSystemNTFS fileSystem, byte[] data, MFTLoadDepth loadDepth, string path) { this.RecordNum = recordNum; this.FileSystem = fileSystem; this.BytesPerSector = fileSystem.BytesPerSector; this.SectorsPerCluster = fileSystem.SectorsPerCluster; this.PartitionStream = fileSystem.Store; Valid = true; _data = data; _path = path; Flags = (RecordFlags)BitConverter.ToUInt16(_data, 22); if (loadDepth != MFTLoadDepth.None) { LoadData(loadDepth); } }
public static MFTRecord Load(ulong recordNum, FileSystemNTFS fileSystem, MFTLoadDepth loadDepth = MFTLoadDepth.Full, string path = "") { ulong startOffset = recordNum * (ulong)fileSystem.SectorsPerMFTRecord * (ulong)fileSystem.BytesPerSector; IDataStream stream; //Special case for MFT - can't read itself if (recordNum == 0) { stream = new SubStream(fileSystem.Store, fileSystem.MFTSector * (ulong)fileSystem.BytesPerSector, (ulong)(fileSystem.SectorsPerMFTRecord * fileSystem.BytesPerSector)); } else { stream = new SubStream(fileSystem.MFT, startOffset, (ulong)(fileSystem.SectorsPerMFTRecord * fileSystem.BytesPerSector)); } // Read the whole record into memory byte[] data = stream.GetBytes(0, stream.StreamLength); return(new MFTRecord(recordNum, fileSystem, data, loadDepth, path)); }
private void LoadAttributes(int startOffset, MFTLoadDepth loadDepth) { _attributes = new List <MFTAttribute>(); while (true) { //Align to 8 byte boundary if (startOffset % 8 != 0) { startOffset = (startOffset / 8 + 1) * 8; } // Read the attribute type and length and determine whether we care about this attribute. AttributeType type = (AttributeType)BitConverter.ToUInt32(_data, startOffset); if (type == AttributeType.End) { break; } int length = BitConverter.ToUInt16(_data, startOffset + 4); if (loadDepth == MFTLoadDepth.NameAttributeOnly && type != AttributeType.FileName) { // Skip this attribute if we're only loading the filename startOffset += length; continue; } MFTAttribute attribute = MFTAttribute.Load(_data, startOffset, this); if (!attribute.NonResident) { switch (attribute.Type) { case AttributeType.StandardInformation: LoadStandardAttribute(startOffset + attribute.ValueOffset); break; case AttributeType.FileName: LoadNameAttribute(startOffset + attribute.ValueOffset); break; case AttributeType.AttributeList: LoadExternalAttributeList(startOffset + attribute.ValueOffset, attribute); break; case AttributeType.VolumeLabel: LoadVolumeLabelAttribute(startOffset + attribute.ValueOffset, (int)attribute.ValueLength); break; } } if (attribute.Valid) { if (attribute.Type == AttributeType.Data) { if (attribute.Name == null) { if (_dataAttribute != null) { Console.Error.WriteLine("Warning: multiple unnamed data streams found on MFT record {0}.", RecordNum); } _dataAttribute = attribute; } else { _namedDataAttributes.Add(attribute); } } _attributes.Add(attribute); } startOffset += (int)attribute.Length; } }
private void LoadAttributes(int startOffset, MFTLoadDepth loadDepth) { _attributes = new List<MFTAttribute>(); while (true) { //Align to 8 byte boundary if (startOffset % 8 != 0) { startOffset = (startOffset / 8 + 1) * 8; } // Read the attribute type and length and determine whether we care about this attribute. AttributeType type = (AttributeType)BitConverter.ToUInt32(_data, startOffset); if (type == AttributeType.End) { break; } int length = BitConverter.ToUInt16(_data, startOffset + 4); if (loadDepth == MFTLoadDepth.NameAttributeOnly && type != AttributeType.FileName) { // Skip this attribute if we're only loading the filename startOffset += length; continue; } MFTAttribute attribute = MFTAttribute.Load(_data, startOffset, this); if (!attribute.NonResident) { switch (attribute.Type) { case AttributeType.StandardInformation: LoadStandardAttribute(startOffset + attribute.ValueOffset); break; case AttributeType.FileName: LoadNameAttribute(startOffset + attribute.ValueOffset); break; case AttributeType.AttributeList: LoadExternalAttributeList(startOffset + attribute.ValueOffset, attribute); break; case AttributeType.VolumeLabel: LoadVolumeLabelAttribute(startOffset + attribute.ValueOffset, (int)attribute.ValueLength); break; } } if (attribute.Valid) { if (attribute.Type == AttributeType.Data) { if (attribute.Name == null) { if (_dataAttribute != null) { Console.Error.WriteLine("Warning: multiple unnamed data streams found on MFT record {0}.", RecordNum); } _dataAttribute = attribute; } else { _namedDataAttributes.Add(attribute); } } _attributes.Add(attribute); } startOffset += (int)attribute.Length; } }
public static MFTRecord Load(ulong recordNum, FileSystemNTFS fileSystem, MFTLoadDepth loadDepth = MFTLoadDepth.Full, string path = "") { ulong startOffset = recordNum * (ulong)fileSystem.SectorsPerMFTRecord * (ulong)fileSystem.BytesPerSector; IDataStream stream; //Special case for MFT - can't read itself if (recordNum == 0) { stream = new SubStream(fileSystem.Store, fileSystem.MFTSector * (ulong)fileSystem.BytesPerSector, (ulong)(fileSystem.SectorsPerMFTRecord * fileSystem.BytesPerSector)); } else { stream = new SubStream(fileSystem.MFT, startOffset, (ulong)(fileSystem.SectorsPerMFTRecord * fileSystem.BytesPerSector)); } // Read the whole record into memory byte[] data = stream.GetBytes(0, stream.StreamLength); return new MFTRecord(recordNum, fileSystem, data, loadDepth, path); }