public File InitializeNew(INtfsContext context, long firstBitmapCluster, ulong numBitmapClusters, long firstRecordsCluster, ulong numRecordsClusters) { BiosParameterBlock bpb = context.BiosParameterBlock; FileRecord fileRec = new FileRecord(bpb.BytesPerSector, bpb.MftRecordSize, (uint)MftIndex); fileRec.Flags = FileRecordFlags.InUse; fileRec.SequenceNumber = 1; _recordCache[MftIndex] = fileRec; _self = new File(context, fileRec); StandardInformation.InitializeNewFile(_self, FileAttributeFlags.Hidden | FileAttributeFlags.System); NtfsStream recordsStream = _self.CreateStream(AttributeType.Data, null, firstRecordsCluster, numRecordsClusters, (uint)bpb.BytesPerCluster); _recordStream = recordsStream.Open(FileAccess.ReadWrite); Wipe(_recordStream); NtfsStream bitmapStream = _self.CreateStream(AttributeType.Bitmap, null, firstBitmapCluster, numBitmapClusters, (uint)bpb.BytesPerCluster); using (Stream s = bitmapStream.Open(FileAccess.ReadWrite)) { Wipe(s); s.SetLength(8); _bitmap = new Bitmap(s, long.MaxValue); } _recordLength = context.BiosParameterBlock.MftRecordSize; _bytesPerSector = context.BiosParameterBlock.BytesPerSector; _bitmap.MarkPresentRange(0, 1); // Write the MFT's own record to itself byte[] buffer = new byte[_recordLength]; fileRec.ToBytes(buffer, 0); _recordStream.Position = 0; _recordStream.Write(buffer, 0, _recordLength); _recordStream.Flush(); return(_self); }
private void VerifyDirectories() { foreach (FileRecord fr in _context.Mft.Records) { if (fr.BaseFile.Value != 0) { continue; } File f = new File(_context, fr); foreach (var stream in f.AllStreams) { if (stream.AttributeType == AttributeType.IndexRoot && stream.Name == "$I30") { IndexView <FileNameRecord, FileRecordReference> dir = new IndexView <FileNameRecord, FileRecordReference>(f.GetIndex("$I30")); foreach (var entry in dir.Entries) { FileRecord refFile = _context.Mft.GetRecord(entry.Value); // Make sure each referenced file actually exists... if (refFile == null) { ReportError("Directory {0} references non-existent file {1}", f, entry.Key); } File referencedFile = new File(_context, refFile); StandardInformation si = referencedFile.StandardInformation; if (si.CreationTime != entry.Key.CreationTime || si.MftChangedTime != entry.Key.MftChangedTime || si.ModificationTime != entry.Key.ModificationTime) { ReportInfo("Directory entry {0} in {1} is out of date", entry.Key, f); } } } } } }
public void UpdateRecordInMft() { if (_dirty) { if (NtfsTransaction.Current != null) { NtfsStream stream = GetStream(AttributeType.StandardInformation, null); StandardInformation si = stream.GetContent <StandardInformation>(); si.MftChangedTime = NtfsTransaction.Current.Timestamp; stream.SetContent(si); } bool fixesApplied = true; while (fixesApplied) { fixesApplied = false; for (int i = 0; i < _records.Count; ++i) { var record = _records[i]; bool fixedAttribute = true; while (record.Size > _mft.RecordSize && fixedAttribute) { fixedAttribute = false; if (!fixedAttribute && !record.IsMftRecord) { foreach (var attr in record.Attributes) { if (!attr.IsNonResident && !_context.AttributeDefinitions.MustBeResident(attr.AttributeType)) { MakeAttributeNonResident(new AttributeReference(record.Reference, attr.AttributeId), (int)attr.DataLength); fixedAttribute = true; break; } } } if (!fixedAttribute) { foreach (var attr in record.Attributes) { if (attr.AttributeType == AttributeType.IndexRoot && ShrinkIndexRoot(attr.Name)) { fixedAttribute = true; break; } } } if (!fixedAttribute) { if (record.Attributes.Count == 1) { fixedAttribute = SplitAttribute(record); } else { if (_records.Count == 1) { CreateAttributeList(); } fixedAttribute = ExpelAttribute(record); } } fixesApplied |= fixedAttribute; } } } _dirty = false; foreach (var record in _records) { _mft.WriteRecord(record); } } }