public FileRecord AllocateRecord(FileRecordFlags flags, bool isMft) { long index; if (isMft) { // Have to take a lot of care extending the MFT itself, to ensure we never end up unable to // bootstrap the file system via the MFT itself - hence why special records are reserved // for MFT's own MFT record overflow. for (int i = 15; i > 11; --i) { FileRecord r = GetRecord(i, false); if (r.BaseFile.SequenceNumber == 0) { r.Reset(); r.Flags |= FileRecordFlags.InUse; WriteRecord(r); return(r); } } throw new IOException("MFT too fragmented - unable to allocate MFT overflow record"); } else { index = _bitmap.AllocateFirstAvailable(FirstAvailableMftIndex); } if (index * _recordLength >= _recordStream.Length) { // Note: 64 is significant, since bitmap extends by 8 bytes (=64 bits) at a time. long newEndIndex = Utilities.RoundUp(index + 1, 64); _recordStream.SetLength(newEndIndex * _recordLength); for (long i = index; i < newEndIndex; ++i) { FileRecord record = new FileRecord(_bytesPerSector, _recordLength, (uint)i); WriteRecord(record); } } FileRecord newRecord = GetRecord(index, true); newRecord.ReInitialize(_bytesPerSector, _recordLength, (uint)index); _recordCache[index] = newRecord; newRecord.Flags = FileRecordFlags.InUse | flags; WriteRecord(newRecord); _self.UpdateRecordInMft(); return(newRecord); }
internal IndexBlock AllocateBlock(IndexEntry parentEntry) { if (_indexStream == null) { _file.CreateStream(AttributeType.IndexAllocation, _name); _indexStream = _file.OpenStream(AttributeType.IndexAllocation, _name, FileAccess.ReadWrite); } if (_indexBitmap == null) { _file.CreateStream(AttributeType.Bitmap, _name); _indexBitmap = new Bitmap(_file.OpenStream(AttributeType.Bitmap, _name, FileAccess.ReadWrite), long.MaxValue); } long idx = _indexBitmap.AllocateFirstAvailable(0); parentEntry.ChildrenVirtualCluster = idx * Utilities.Ceil(_bpb.IndexBufferSize, _bpb.SectorsPerCluster * _bpb.BytesPerSector); parentEntry.Flags |= IndexEntryFlags.Node; IndexBlock block = IndexBlock.Initialize(this, false, parentEntry, _bpb); _blockCache[parentEntry.ChildrenVirtualCluster] = block; return(block); }