/// <summary> /// The constructor for a file contained as a hidden data stream. /// </summary> public FileNTFS(MFTRecord record, MFTAttribute attr, string path) { _record = record; _stream = new NTFSFileStream(_record.PartitionStream, _record, attr); FileSystem = record.FileSystem; Deleted = _record.Deleted; Name = PathUtils.MakeFileNameValid(record.FileName + "_" + attr.Name); Path = PathUtils.Combine(path, Name); }
public NTFSFileStream(IDataStream partition, MFTRecord record, MFTAttribute attr) { if (attr != null) { _nonResident = attr.NonResident; if (_nonResident) { _runs = attr.Runs; _length = attr.DataSize; } else { _residentStream = attr.ResidentData; _length = attr.ResidentData.StreamLength; } } _record = record; _partitionStream = partition; }
public FolderNTFS(MFTRecord record, string path, bool isRoot = false) { _record = record; FileSystem = record.FileSystem; Deleted = _record.Deleted; _indexRoot = new NTFSFileStream(_record.PartitionStream, _record, AttributeType.IndexRoot); MFTAttribute attr = _record.GetAttribute(AttributeType.IndexAllocation); if (attr != null) { _indexAllocation = new NTFSFileStream(_record.PartitionStream, _record, AttributeType.IndexAllocation); } if (isRoot) // root { Root = true; Name = FileSystem.Store.DeviceID; Path = FileSystem.Store.DeviceID; foreach (FileSystemNode node in GetChildren("$Volume")) { FileNTFS file = node as FileNTFS; if (file != null && file.VolumeLabel != "") { Name = file.VolumeLabel; break; } } } else { Name = PathUtils.MakeFileNameValid(record.FileName); if (!string.IsNullOrEmpty(path)) { Path = PathUtils.Combine(path, Name); } else { // We don't know the path Path = PathUtils.Combine(FileSystem.Store.DeviceID, "?", Name); } } }
private void LoadExternalAttributeList(int startOffset, MFTAttribute attrList) { int offset = 0; while (true) { //Align to 8 byte boundary if (offset % 8 != 0) { offset = (offset / 8 + 1) * 8; } // Load the header for this external attribute reference. AttributeType type = (AttributeType)BitConverter.ToUInt32(_data, offset + startOffset + 0x0); // 0xFFFFFFFF marks end of attributes. if (offset == attrList.ValueLength || type == AttributeType.End) { break; } ushort length = BitConverter.ToUInt16(_data, offset + startOffset + 0x4); byte nameLength = _data[offset + startOffset + 0x6]; ushort id = BitConverter.ToUInt16(_data, offset + startOffset + 0x18); ulong vcn = BitConverter.ToUInt64(_data, offset + startOffset + 0x8); ulong extensionRecordNumber = (BitConverter.ToUInt64(_data, offset + startOffset + 0x10) & 0x00000000FFFFFFFF); if (extensionRecordNumber != RecordNum && extensionRecordNumber != MFTRecordNumber) // TODO: Are these ever different? // Load the MFT extension record, locate the attribute we want, and copy it over. { MFTRecord extensionRecord = MFTRecord.Load(extensionRecordNumber, this.FileSystem); if (extensionRecord.Valid) { foreach (MFTAttribute externalAttribute in extensionRecord._attributes) { if (id == externalAttribute.Id) { if (externalAttribute.NonResident && externalAttribute.Type == AttributeType.Data) { // Find the corresponding data attribute on this record and merge the runlists bool merged = false; foreach (MFTAttribute attribute in _attributes) { if (attribute.Type == AttributeType.Data && externalAttribute.Name == attribute.Name) { MergeRunLists(ref attribute.Runs, externalAttribute.Runs); merged = true; break; } } if (!merged) { this._attributes.Add(externalAttribute); } } else { this._attributes.Add(externalAttribute); } } } } } offset += 0x1A + (nameLength * 2); } }
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; } }