public void Test_STREAM_VIEW_2() { Stream b = null; List <Sector> temp = new List <Sector>(); StreamView sv = new StreamView(temp, 512, b); sv.Write(BitConverter.GetBytes(1), 0, 4); sv.Seek(0, SeekOrigin.Begin); BinaryReader br = new BinaryReader(sv); Int32 t = br.ReadInt32(); Assert.IsTrue(t == 1); }
public void Test_STREAM_VIEW_LARGE_DATA() { Stream b = null; List <Sector> temp = new List <Sector>(); StreamView sv = new StreamView(temp, 512, b); for (int i = 0; i < 200; i++) { sv.Write(BitConverter.GetBytes(i), 0, 4); } sv.Seek(0, SeekOrigin.Begin); BinaryReader br = new BinaryReader(sv); for (int i = 0; i < 200; i++) { Assert.IsTrue(i == br.ReadInt32(), "Failed with " + i.ToString()); } }
/// <summary> /// Allocate space, setup sectors id and refresh header /// for the new or updated mini sector chain. /// </summary> /// <param name="sectorChain">The new MINI sector chain</param> private void SetMiniSectorChain(IList<Sector> sectorChain) { var miniFAT = GetSectorChain(_header.FirstMiniFATSectorId, SectorType.Normal); var miniStream = GetSectorChain(RootEntry.StartSector, SectorType.Normal); var miniFATView = new StreamView( miniFAT, GetSectorSize(), _header.MiniFATSectorsNumber*Sector.MinisectorSize, SourceStream ); var miniStreamView = new StreamView( miniStream, GetSectorSize(), RootStorage.Size, SourceStream); // Set updated/new sectors within the ministream foreach (var sector in sectorChain) { if (sector.Id != -1) { // Overwrite miniStreamView.Seek(Sector.MinisectorSize*sector.Id, SeekOrigin.Begin); miniStreamView.Write(sector.GetData(), 0, Sector.MinisectorSize); } else { // Allocate, position ministream at the end of already allocated // ministream's sectors miniStreamView.Seek(RootStorage.Size, SeekOrigin.Begin); miniStreamView.Write(sector.GetData(), 0, Sector.MinisectorSize); sector.Id = (int) (miniStreamView.Position - Sector.MinisectorSize)/Sector.MinisectorSize; RootStorage.DirEntry.Size = miniStreamView.Length; } } // Update miniFAT for (var i = 0; i < sectorChain.Count - 1; i++) { var currentId = sectorChain[i].Id; var nextId = sectorChain[i + 1].Id; //AssureLength(miniFATView, Math.Max(currentId * SIZE_OF_SID, nextId * SIZE_OF_SID)); miniFATView.Seek(currentId*4, SeekOrigin.Begin); miniFATView.Write(BitConverter.GetBytes(nextId), 0, 4); } // Write End of Chain in MiniFAT miniFATView.Seek(sectorChain[sectorChain.Count - 1].Id*SizeOfSID, SeekOrigin.Begin); miniFATView.Write(BitConverter.GetBytes(Sector.Endofchain), 0, 4); // Update sector chains SetNormalSectorChain(miniStreamView.BaseSectorChain); SetNormalSectorChain(miniFATView.BaseSectorChain); //Update HEADER and root storage when ministream changes if (miniFAT.Count > 0) { RootStorage.DirEntry.StartSector = miniStream[0].Id; _header.MiniFATSectorsNumber = (uint) miniFAT.Count; _header.FirstMiniFATSectorId = miniFAT[0].Id; } }
/// <summary> /// Sets the data for the current stream /// </summary> /// <param name="cfItem"></param> /// <param name="buffer"></param> /// <exception cref="CFException">Raised when <see cref="buffer" /> is null</exception> private void SetStreamData(CFItem cfItem, Byte[] buffer) { if (buffer == null) throw new CFException("Parameter [buffer] cannot be null"); // Quick and dirty :-) if (buffer.Length == 0) return; var directoryEntry = cfItem.DirEntry; var sectorType = SectorType.Normal; var sectorSize = GetSectorSize(); if (buffer.Length < _header.MinSizeStandardStream) { sectorType = SectorType.Mini; sectorSize = Sector.MinisectorSize; } // Check for transition ministream -> stream: // Only in this case we need to free old sectors, // otherwise they will be overwritten. if (directoryEntry.StartSector != Sector.Endofchain) { if ( (buffer.Length < _header.MinSizeStandardStream && directoryEntry.Size > _header.MinSizeStandardStream) || (buffer.Length > _header.MinSizeStandardStream && directoryEntry.Size < _header.MinSizeStandardStream) ) { if (directoryEntry.Size < _header.MinSizeStandardStream) { FreeMiniChain(GetMiniSectorChain(directoryEntry.StartSector), _eraseFreeSectors); } else { FreeChain(GetNormalSectorChain(directoryEntry.StartSector), _eraseFreeSectors); } directoryEntry.Size = 0; directoryEntry.StartSector = Sector.Endofchain; } } var sectorChain = GetSectorChain(directoryEntry.StartSector, sectorType); Queue<Sector> freeList = null; if (_sectorRecycle) freeList = FindFreeSectors(sectorType); // Collect available free sectors var streamView = new StreamView(sectorChain, sectorSize, buffer.Length, freeList, SourceStream); streamView.Write(buffer, 0, buffer.Length); switch (sectorType) { case SectorType.Normal: SetNormalSectorChain(streamView.BaseSectorChain); break; case SectorType.Mini: SetMiniSectorChain(streamView.BaseSectorChain); break; } if (streamView.BaseSectorChain.Count > 0) { directoryEntry.StartSector = streamView.BaseSectorChain[0].Id; directoryEntry.Size = buffer.Length; } else { directoryEntry.StartSector = Sector.Endofchain; directoryEntry.Size = 0; } }
/// <summary> /// Allocate space, setup sectors id and refresh header /// for the new or updated FAT sector chain. /// </summary> /// <param name="sectorChain">The new or updated generic sector chain</param> private void SetFATSectorChain(IList<Sector> sectorChain) { var fatSectors = GetSectorChain(-1, SectorType.FAT); var fatStream = new StreamView( fatSectors, GetSectorSize(), _header.FATSectorsNumber*GetSectorSize(), SourceStream ); // Write FAT chain values -- for (var i = 0; i < sectorChain.Count - 1; i++) { var sN = sectorChain[i + 1]; var sC = sectorChain[i]; fatStream.Seek(sC.Id*4, SeekOrigin.Begin); fatStream.Write(BitConverter.GetBytes(sN.Id), 0, 4); } fatStream.Seek(sectorChain[sectorChain.Count - 1].Id*4, SeekOrigin.Begin); fatStream.Write(BitConverter.GetBytes(Sector.Endofchain), 0, 4); // Merge chain to CFS SetDIFATSectorChain(fatStream.BaseSectorChain); }
/// <summary> /// Setup the DIFAT sector chain /// </summary> /// <param name="faTsectorChain">A FAT sector chain</param> private void SetDIFATSectorChain(List<Sector> faTsectorChain) { // Get initial sector's count _header.FATSectorsNumber = faTsectorChain.Count; // Allocate Sectors foreach (var s in faTsectorChain) { if (s.Id != -1) continue; _sectors.Add(s); s.Id = _sectors.Count - 1; s.Type = SectorType.FAT; } // Sector count... var nCurrentSectors = _sectors.Count; // Temp DIFAT count var nDIFATSectors = (int) _header.DIFATSectorsNumber; if (faTsectorChain.Count > HeaderDIFATEntriesCount) { nDIFATSectors = Ceiling((double) (faTsectorChain.Count - HeaderDIFATEntriesCount)/_difatSectorFATEntriesCount); nDIFATSectors = LowSaturation(nDIFATSectors - (int) _header.DIFATSectorsNumber); //required DIFAT } // ...sum with new required DIFAT sectors count nCurrentSectors += nDIFATSectors; // ReCheck FAT bias while (_header.FATSectorsNumber*_fatSectorEntriesCount < nCurrentSectors) { var extraFATSector = new Sector(GetSectorSize(), SourceStream); _sectors.Add(extraFATSector); extraFATSector.Id = _sectors.Count - 1; extraFATSector.Type = SectorType.FAT; faTsectorChain.Add(extraFATSector); _header.FATSectorsNumber++; nCurrentSectors++; //... so, adding a FAT sector may induce DIFAT sectors to increase by one // and consequently this may induce ANOTHER FAT sector (TO-THINK: May this condition occure ?) if (nDIFATSectors*_difatSectorFATEntriesCount >= (_header.FATSectorsNumber > HeaderDIFATEntriesCount ? _header.FATSectorsNumber - HeaderDIFATEntriesCount : 0)) continue; nDIFATSectors++; nCurrentSectors++; } var difatSectors = GetSectorChain(-1, SectorType.DIFAT); var difatStream = new StreamView(difatSectors, GetSectorSize(), SourceStream); // Write DIFAT Sectors (if required) // Save room for the following chaining for (var i = 0; i < faTsectorChain.Count; i++) { if (i < HeaderDIFATEntriesCount) _header.DIFAT[i] = faTsectorChain[i].Id; else { // room for DIFAT chaining at the end of any DIFAT sector (4 bytes) if (i != HeaderDIFATEntriesCount && (i - HeaderDIFATEntriesCount)%_difatSectorFATEntriesCount == 0) { var temp = new byte[sizeof (int)]; difatStream.Write(temp, 0, sizeof (int)); } difatStream.Write(BitConverter.GetBytes(faTsectorChain[i].Id), 0, sizeof (int)); } } // Allocate room for DIFAT sectors foreach (var sector in difatStream.BaseSectorChain) { if (sector.Id != -1) continue; _sectors.Add(sector); sector.Id = _sectors.Count - 1; sector.Type = SectorType.DIFAT; } _header.DIFATSectorsNumber = (uint) nDIFATSectors; // Chain first sector if (difatStream.BaseSectorChain != null && difatStream.BaseSectorChain.Count > 0) { _header.FirstDIFATSectorId = difatStream.BaseSectorChain[0].Id; // Update header information _header.DIFATSectorsNumber = (uint) difatStream.BaseSectorChain.Count; // Write chaining information at the end of DIFAT Sectors for (var i = 0; i < difatStream.BaseSectorChain.Count - 1; i++) { Buffer.BlockCopy( BitConverter.GetBytes(difatStream.BaseSectorChain[i + 1].Id), 0, difatStream.BaseSectorChain[i].GetData(), GetSectorSize() - sizeof (int), 4); } Buffer.BlockCopy( BitConverter.GetBytes(Sector.Endofchain), 0, difatStream.BaseSectorChain[difatStream.BaseSectorChain.Count - 1].GetData(), GetSectorSize() - sizeof (int), sizeof (int) ); } else _header.FirstDIFATSectorId = Sector.Endofchain; // Mark DIFAT Sectors in FAT var fatSv = new StreamView(faTsectorChain, GetSectorSize(), _header.FATSectorsNumber*GetSectorSize(), SourceStream); for (var i = 0; i < _header.DIFATSectorsNumber; i++) { fatSv.Seek(difatStream.BaseSectorChain[i].Id*4, SeekOrigin.Begin); fatSv.Write(BitConverter.GetBytes(Sector.DifSector), 0, 4); } for (var i = 0; i < _header.FATSectorsNumber; i++) { fatSv.Seek(fatSv.BaseSectorChain[i].Id*4, SeekOrigin.Begin); fatSv.Write(BitConverter.GetBytes(Sector.FATSector), 0, 4); } _header.FATSectorsNumber = fatSv.BaseSectorChain.Count; }
private void FreeMiniChain(IList<Sector> sectorChain, bool zeroSector) { var zeroedMiniSector = new byte[Sector.MinisectorSize]; var miniFAT = GetSectorChain(_header.FirstMiniFATSectorId, SectorType.Normal); var miniStream = GetSectorChain(RootEntry.StartSector, SectorType.Normal); var miniFATView = new StreamView(miniFAT, GetSectorSize(), _header.MiniFATSectorsNumber*Sector.MinisectorSize, SourceStream); var miniStreamView = new StreamView(miniStream, GetSectorSize(), RootStorage.Size, SourceStream); // Set updated/new sectors within the ministream if (zeroSector) { foreach (var sector in sectorChain) { if (sector.Id == -1) continue; // Overwrite miniStreamView.Seek(Sector.MinisectorSize*sector.Id, SeekOrigin.Begin); miniStreamView.Write(zeroedMiniSector, 0, Sector.MinisectorSize); } } // Update miniFAT for (var i = 0; i < sectorChain.Count - 1; i++) { var currentId = sectorChain[i].Id; miniFATView.Seek(currentId*4, SeekOrigin.Begin); miniFATView.Write(BitConverter.GetBytes(Sector.FreeSector), 0, 4); } //AssureLength(miniFATView, sectorChain[sectorChain.Count - 1].Id * SIZE_OF_SID); // Write End of Chain in MiniFAT miniFATView.Seek(sectorChain[sectorChain.Count - 1].Id*SizeOfSID, SeekOrigin.Begin); miniFATView.Write(BitConverter.GetBytes(Sector.FreeSector), 0, 4); // Update sector chains SetNormalSectorChain(miniStreamView.BaseSectorChain); SetNormalSectorChain(miniFATView.BaseSectorChain); //Update HEADER and root storage when ministream changes if (miniFAT.Count > 0) { RootStorage.DirEntry.StartSector = miniStream[0].Id; _header.MiniFATSectorsNumber = (uint) miniFAT.Count; _header.FirstMiniFATSectorId = miniFAT[0].Id; } }
private void FreeChain(IList<Sector> sectorChain, bool zeroSector) { var fat = GetSectorChain(-1, SectorType.FAT); var fatView = new StreamView(fat, GetSectorSize(), fat.Count*GetSectorSize(), SourceStream); // Zeroes out sector data (if requested) if (zeroSector) { foreach (var sector in sectorChain) sector.ZeroData(); } // Update FAT marking unallocated sectors for (var i = 0; i < sectorChain.Count - 1; i++) { var currentId = sectorChain[i].Id; //AssureLength(FATView, Math.Max(currentId * SIZE_OF_SID, nextId * SIZE_OF_SID)); fatView.Seek(currentId*4, SeekOrigin.Begin); fatView.Write(BitConverter.GetBytes(Sector.FreeSector), 0, 4); } }
/// <summary> /// Check for transaction lock sector addition and mark it in the FAT. /// </summary> private void CheckForLockSector() { //If transaction lock has been added and not yet allocated in the FAT... if (TransactionLockAdded && !TransactionLockAllocated) { var fatStream = new StreamView(GetFatSectorChain(), GetSectorSize(), SourceStream); fatStream.Seek(LockSectorId*4, SeekOrigin.Begin); fatStream.Write(BitConverter.GetBytes(Sector.Endofchain), 0, 4); TransactionLockAllocated = true; } }