Example #1
0
            protected void CreateBlockIfNeeded()
            {
                if (buffer != null && buffer.HasRemaining())
                {
                    return;
                }

                int thisBlock = nextBlock;

                // Allocate a block if needed, otherwise figure
                //  out what the next block will be
                if (thisBlock == POIFSConstants.END_OF_CHAIN)
                {
                    thisBlock = pStream.blockStore.GetFreeBlock();
                    loopDetector.Claim(thisBlock);

                    // We're on the end of the chain
                    nextBlock = POIFSConstants.END_OF_CHAIN;

                    // Mark the previous block as carrying on to us if needed
                    if (prevBlock != POIFSConstants.END_OF_CHAIN)
                    {
                        pStream.blockStore.SetNextBlock(prevBlock, thisBlock);
                    }
                    pStream.blockStore.SetNextBlock(thisBlock, POIFSConstants.END_OF_CHAIN);

                    // If we've just written the first block on a
                    //  new stream, save the start block offset
                    if (pStream.startBlock == POIFSConstants.END_OF_CHAIN)
                    {
                        pStream.startBlock = thisBlock;
                    }
                }
                else
                {
                    loopDetector.Claim(thisBlock);
                    nextBlock = pStream.blockStore.GetNextBlock(thisBlock);
                }

                buffer = pStream.blockStore.CreateBlockIfNeeded(thisBlock);

                // Update pointers
                prevBlock = thisBlock;
            }
Example #2
0
        private void ReadBAT(int batAt, ChainLoopDetector loopDetector)
        {
            loopDetector.Claim(batAt);
            ByteBuffer fatData = GetBlockAt(batAt);
            // byte[] fatData = GetBlockAt(batAt);
            BATBlock bat = BATBlock.CreateBATBlock(bigBlockSize, fatData);

            bat.OurBlockIndex = batAt;
            _bat_blocks.Add(bat);
        }
Example #3
0
        /**
         * Load the block, extending the underlying stream if needed
         */
        public override ByteBuffer CreateBlockIfNeeded(int offset)
        {
            bool firstInStore = false;

            // If we are the first block to be allocated, initialise the stream
            if (_mini_stream.GetStartBlock() == POIFSConstants.END_OF_CHAIN)
            {
                firstInStore = true;
            }

            // Try to Get it without extending the stream
            if (!firstInStore)
            {
                try
                {
                    return(GetBlockAt(offset));
                }catch (IndexOutOfRangeException) {}
            }

            // Need to extend the stream
            // TODO Replace this with proper append support
            // For now, do the extending by hand...

            // Ask for another block
            int newBigBlock = _filesystem.GetFreeBlock();

            _filesystem.CreateBlockIfNeeded(newBigBlock);
            // If we are the first block to be allocated, initialise the stream
            if (firstInStore)
            {
                _filesystem.PropertyTable.Root.StartBlock = (newBigBlock);
                _mini_stream = new NPOIFSStream(_filesystem, newBigBlock);
            }
            else
            {
                // Tack it onto the end of our chain
                ChainLoopDetector loopDetector = _filesystem.GetChainLoopDetector();
                int block = _mini_stream.GetStartBlock();
                while (true)
                {
                    loopDetector.Claim(block);
                    int next = _filesystem.GetNextBlock(block);
                    if (next == POIFSConstants.END_OF_CHAIN)
                    {
                        break;
                    }
                    block = next;
                }
                _filesystem.SetNextBlock(block, newBigBlock);
            }
            _filesystem.SetNextBlock(newBigBlock, POIFSConstants.END_OF_CHAIN);

            // Now try again, to get the real small block
            return(CreateBlockIfNeeded(offset));
        }
Example #4
0
            public ByteBuffer Next()
            {
                if (nextBlock == POIFSConstants.END_OF_CHAIN)
                {
                    throw new IndexOutOfRangeException("Can't read past the end of the stream");
                }

                try
                {
                    loopDetector.Claim(nextBlock);
                    //byte[] data = blockStore.GetBlockAt(nextBlock);
                    ByteBuffer data = pStream.blockStore.GetBlockAt(nextBlock);
                    nextBlock = pStream.blockStore.GetNextBlock(nextBlock);
                    return(data);
                }
                catch (IOException e)
                {
                    throw new RuntimeException(e.Message);
                }
            }
Example #5
0
        internal void Free(ChainLoopDetector loopDetector)
        {
            int nextBlock = startBlock;

            while (nextBlock != POIFSConstants.END_OF_CHAIN)
            {
                int thisBlock = nextBlock;
                loopDetector.Claim(thisBlock);
                nextBlock = blockStore.GetNextBlock(thisBlock);
                blockStore.SetNextBlock(thisBlock, POIFSConstants.UNUSED_BLOCK);
            }
            this.startBlock = POIFSConstants.END_OF_CHAIN;
        }
Example #6
0
        /**
         * Read and process the PropertiesTable and the
         *  FAT / XFAT blocks, so that we're Ready to
         *  work with the file
         */
        private void ReadCoreContents()
        {
            // Grab the block size
            bigBlockSize = _header.BigBlockSize;

            // Each block should only ever be used by one of the
            //  FAT, XFAT or Property Table. Ensure it does
            ChainLoopDetector loopDetector = GetChainLoopDetector();

            // Read the FAT blocks
            foreach (int fatAt in _header.BATArray)
            {
                ReadBAT(fatAt, loopDetector);
            }
            // Work out how many FAT blocks remain in the XFATs
            int remainingFATs = _header.BATCount - _header.BATArray.Length;

            // Now read the XFAT blocks, and the FATs within them
            BATBlock xfat;
            int      nextAt = _header.XBATIndex;

            for (int i = 0; i < _header.XBATCount; i++)
            {
                loopDetector.Claim(nextAt);
                ByteBuffer fatData = GetBlockAt(nextAt);
                xfat = BATBlock.CreateBATBlock(bigBlockSize, fatData);
                xfat.OurBlockIndex = nextAt;
                nextAt             = xfat.GetValueAt(bigBlockSize.GetXBATEntriesPerBlock());
                _xbat_blocks.Add(xfat);
                // Process all the (used) FATs from this XFAT
                int xbatFATs = Math.Min(remainingFATs, bigBlockSize.GetXBATEntriesPerBlock());
                for (int j = 0; j < xbatFATs; j++)
                {
                    int fatAt = xfat.GetValueAt(j);
                    if (fatAt == POIFSConstants.UNUSED_BLOCK || fatAt == POIFSConstants.END_OF_CHAIN)
                    {
                        break;
                    }
                    ReadBAT(fatAt, loopDetector);
                }
                remainingFATs -= xbatFATs;
            }

            // We're now able to load steams
            // Use this to read in the properties
            _property_table = new NPropertyTable(_header, this);

            // Finally read the Small Stream FAT (SBAT) blocks
            BATBlock        sfat;
            List <BATBlock> sbats = new List <BATBlock>();

            _mini_store = new NPOIFSMiniStore(this, _property_table.Root, sbats, _header);
            nextAt      = _header.SBATStart;
            for (int i = 0; i < _header.SBATCount; i++)
            {
                loopDetector.Claim(nextAt);
                ByteBuffer fatData = GetBlockAt(nextAt);
                sfat = BATBlock.CreateBATBlock(bigBlockSize, fatData);
                sfat.OurBlockIndex = nextAt;
                sbats.Add(sfat);
                nextAt = GetNextBlock(nextAt);
            }
        }
Example #7
0
        /**
         * Finds a free block, and returns its offset.
         * This method will extend the file if needed, and if doing
         *  so, allocate new FAT blocks to Address the extra space.
         */
        public override int GetFreeBlock()
        {
            int sectorsPerSBAT = _filesystem.GetBigBlockSizeDetails().GetBATEntriesPerBlock();

            // First up, do we have any spare ones?
            int offset = 0;

            for (int i = 0; i < _sbat_blocks.Count; i++)
            {
                // Check this one
                BATBlock sbat = _sbat_blocks[i];
                if (sbat.HasFreeSectors)
                {
                    // Claim one of them and return it
                    for (int j = 0; j < sectorsPerSBAT; j++)
                    {
                        int sbatValue = sbat.GetValueAt(j);
                        if (sbatValue == POIFSConstants.UNUSED_BLOCK)
                        {
                            // Bingo
                            return(offset + j);
                        }
                    }
                }

                // Move onto the next SBAT
                offset += sectorsPerSBAT;
            }

            // If we Get here, then there aren't any
            //  free sectors in any of the SBATs
            // So, we need to extend the chain and add another

            // Create a new BATBlock
            BATBlock newSBAT    = BATBlock.CreateEmptyBATBlock(_filesystem.GetBigBlockSizeDetails(), false);
            int      batForSBAT = _filesystem.GetFreeBlock();

            newSBAT.OurBlockIndex = batForSBAT;

            // Are we the first SBAT?
            if (_header.SBATCount == 0)
            {
                // Tell the header that we've got our first SBAT there
                _header.SBATStart      = batForSBAT;
                _header.SBATBlockCount = 1;
            }
            else
            {
                // Find the end of the SBAT stream, and add the sbat in there
                ChainLoopDetector loopDetector = _filesystem.GetChainLoopDetector();
                int batOffset = _header.SBATStart;
                while (true)
                {
                    loopDetector.Claim(batOffset);
                    int nextBat = _filesystem.GetNextBlock(batOffset);
                    if (nextBat == POIFSConstants.END_OF_CHAIN)
                    {
                        break;
                    }
                    batOffset = nextBat;
                }

                // Add it in at the end
                _filesystem.SetNextBlock(batOffset, batForSBAT);

                // And update the count
                _header.SBATBlockCount = _header.SBATCount + 1;
            }

            // Finish allocating
            _filesystem.SetNextBlock(batForSBAT, POIFSConstants.END_OF_CHAIN);
            _sbat_blocks.Add(newSBAT);

            // Return our first spot
            return(offset);
        }
Example #8
0
 private void ReadBAT(int batAt, ChainLoopDetector loopDetector)
 {
     loopDetector.Claim(batAt);
     ByteBuffer fatData = GetBlockAt(batAt);
     // byte[] fatData = GetBlockAt(batAt);
     BATBlock bat = BATBlock.CreateBATBlock(bigBlockSize, fatData);
     bat.OurBlockIndex = batAt;
     _bat_blocks.Add(bat);
 }