/// <summary> /// Scan FAT o miniFAT for free sectors to reuse. /// </summary> /// <param name="sType">Type of sector to look for</param> /// <returns>A stack of available sectors or minisectors already allocated</returns> internal Queue<Sector> FindFreeSectors(SectorType sType) { var freeList = new Queue<Sector>(); if (sType == SectorType.Normal) { var fatChain = GetSectorChain(-1, SectorType.FAT); var fatStream = new StreamView(fatChain, GetSectorSize(), _header.FATSectorsNumber*GetSectorSize(), SourceStream); var idx = 0; while (idx < _sectors.Count) { var id = fatStream.ReadInt32(); if (id == Sector.FreeSector) { if (_sectors[idx] == null) { var sector = new Sector(GetSectorSize(), SourceStream) {Id = idx}; _sectors[idx] = sector; } freeList.Enqueue(_sectors[idx]); } idx++; } } else { var miniFAT = GetSectorChain(_header.FirstMiniFATSectorId, SectorType.Normal); var miniFATView = new StreamView(miniFAT, GetSectorSize(), _header.MiniFATSectorsNumber*Sector.MinisectorSize, SourceStream); var miniStream = GetSectorChain(RootEntry.StartSector, SectorType.Normal); var miniStreamView = new StreamView(miniStream, GetSectorSize(), RootStorage.Size, SourceStream); long ptr = 0; var nMinisectors = (int) (miniStreamView.Length/Sector.MinisectorSize); while (ptr < nMinisectors) { //AssureLength(miniStreamView, (int)miniFATView.Length); var id = miniFATView.ReadInt32(); ptr += 4; if (id != Sector.FreeSector) continue; var miniSector = new Sector(Sector.MinisectorSize, SourceStream) { Id = (int) ((ptr - 4)/4), Type = SectorType.Mini }; miniStreamView.Seek(miniSector.Id*Sector.MinisectorSize, SeekOrigin.Begin); miniStreamView.Read(miniSector.GetData(), 0, Sector.MinisectorSize); freeList.Enqueue(miniSector); } } return freeList; }
/// <summary> /// Get a mini sector chain /// </summary> /// <param name="sectorId">First sector id of the required chain</param> /// <returns>A list of mini sectors (64 bytes)</returns> private List<Sector> GetMiniSectorChain(int sectorId) { var result = new List<Sector>(); if (sectorId == Sector.Endofchain) return result; var miniFAT = GetNormalSectorChain(_header.FirstMiniFATSectorId); var miniStream = GetNormalSectorChain(RootEntry.StartSector); var miniFATView = new StreamView(miniFAT, GetSectorSize(), _header.MiniFATSectorsNumber*Sector.MinisectorSize, SourceStream); var miniStreamView = new StreamView(miniStream, GetSectorSize(), RootStorage.Size, SourceStream); var miniFATReader = new BinaryReader(miniFATView); var nextSectorId = sectorId; while (true) { if (nextSectorId == Sector.Endofchain) break; var miniSector = new Sector(Sector.MinisectorSize, SourceStream) { Id = nextSectorId, Type = SectorType.Mini }; miniStreamView.Seek(nextSectorId*Sector.MinisectorSize, SeekOrigin.Begin); miniStreamView.Read(miniSector.GetData(), 0, Sector.MinisectorSize); result.Add(miniSector); miniFATView.Seek(nextSectorId*4, SeekOrigin.Begin); nextSectorId = miniFATReader.ReadInt32(); } return result; }