Exemple #1
0
        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);
        }
Exemple #2
0
        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;
            }
        }