Ejemplo n.º 1
0
        /// <summary>
        /// create a BlockAllocationTableReader for an existing filesystem. Side
        /// effect: when this method finishes, the BAT blocks will have
        /// been Removed from the raw block list, and any blocks labeled as
        /// 'unused' in the block allocation table will also have been
        /// Removed from the raw block list. </summary>
        /// <param name="bigBlockSizse">the poifs bigBlockSize</param>
        /// <param name="block_count">the number of BAT blocks making up the block allocation table</param>
        /// <param name="block_array">the array of BAT block indices from the
        /// filesystem's header</param>
        /// <param name="xbat_count">the number of XBAT blocks</param>
        /// <param name="xbat_index">the index of the first XBAT block</param>
        /// <param name="raw_block_list">the list of RawDataBlocks</param>
        public BlockAllocationTableReader(POIFSBigBlockSize bigBlockSizse,
                                          int block_count,
                                          int[] block_array,
                                          int xbat_count,
                                          int xbat_index,
                                          BlockList raw_block_list)
            : this(bigBlockSizse)
        {
            SanityCheckBlockCount(block_count);

            RawDataBlock[] blocks = new RawDataBlock[block_count];
            int limit = Math.Min(block_count, block_array.Length);
            int block_index;

            for (block_index = 0; block_index < limit; block_index++)
            {
                int nextOffset = block_array[block_index];
                if (nextOffset > raw_block_list.BlockCount())
                {
                    throw new IOException("Your file contains " + raw_block_list.BlockCount() +
                                           " sectors, but the initial DIFAT array at index " + block_index +
                                           " referenced block # " + nextOffset + ". This isn't allowed and " +
                                           " your file is corrupt");
                }

                blocks[block_index] = (RawDataBlock)raw_block_list.Remove(nextOffset);
            }
            if (block_index < block_count)
            {

                // must have extended blocks
                if (xbat_index < 0)
                {
                    throw new IOException(
                        "BAT count exceeds limit, yet XBAT index indicates no valid entries");
                }
                int chain_index = xbat_index;
                int max_entries_per_block = BATBlock.EntriesPerXBATBlock;
                int chain_index_offset = BATBlock.XBATChainOffset;

                // Each XBAT block contains either:
                //  (maximum number of sector indexes) + index of next XBAT
                //  some sector indexes + FREE sectors to max # + EndOfChain
                for (int j = 0; j < xbat_count; j++)
                {
                    limit = Math.Min(block_count - block_index,
                                     max_entries_per_block);
                    byte[] data = raw_block_list.Remove(chain_index).Data;
                    int offset = 0;

                    for (int k = 0; k < limit; k++)
                    {
                        blocks[block_index++] =
                            (RawDataBlock)raw_block_list.Remove(LittleEndian.GetInt(data, offset));
                        offset += LittleEndianConsts.INT_SIZE;
                    }
                    chain_index = LittleEndian.GetInt(data, chain_index_offset);
                    if (chain_index == POIFSConstants.END_OF_CHAIN)
                    {
                        break;
                    }
                }
            }
            if (block_index != block_count)
            {
                throw new IOException("Could not find all blocks");
            }

            // now that we have all of the raw data blocks, go through and
            // create the indices
            SetEntries((ListManagedBlock[])blocks, raw_block_list);
        }
        /// <summary>
        /// create a BlockAllocationTableReader for an existing filesystem. Side
        /// effect: when this method finishes, the BAT blocks will have
        /// been Removed from the raw block list, and any blocks labeled as
        /// 'unused' in the block allocation table will also have been
        /// Removed from the raw block list. </summary>
        /// <param name="bigBlockSizse">the poifs bigBlockSize</param>
        /// <param name="block_count">the number of BAT blocks making up the block allocation table</param>
        /// <param name="block_array">the array of BAT block indices from the
        /// filesystem's header</param>
        /// <param name="xbat_count">the number of XBAT blocks</param>
        /// <param name="xbat_index">the index of the first XBAT block</param>
        /// <param name="raw_block_list">the list of RawDataBlocks</param>
        public BlockAllocationTableReader(POIFSBigBlockSize bigBlockSizse,
                                          int block_count,
                                          int[] block_array,
                                          int xbat_count,
                                          int xbat_index,
                                          BlockList raw_block_list)
            : this(bigBlockSizse)
        {
            SanityCheckBlockCount(block_count);

            RawDataBlock[] blocks = new RawDataBlock[block_count];
            int            limit  = Math.Min(block_count, block_array.Length);
            int            block_index;

            for (block_index = 0; block_index < limit; block_index++)
            {
                int nextOffset = block_array[block_index];
                if (nextOffset > raw_block_list.BlockCount())
                {
                    throw new IOException("Your file contains " + raw_block_list.BlockCount() +
                                          " sectors, but the initial DIFAT array at index " + block_index +
                                          " referenced block # " + nextOffset + ". This isn't allowed and " +
                                          " your file is corrupt");
                }

                blocks[block_index] = (RawDataBlock)raw_block_list.Remove(nextOffset);
            }
            if (block_index < block_count)
            {
                // must have extended blocks
                if (xbat_index < 0)
                {
                    throw new IOException(
                              "BAT count exceeds limit, yet XBAT index indicates no valid entries");
                }
                int chain_index           = xbat_index;
                int max_entries_per_block = BATBlock.EntriesPerXBATBlock;
                int chain_index_offset    = BATBlock.XBATChainOffset;

                // Each XBAT block contains either:
                //  (maximum number of sector indexes) + index of next XBAT
                //  some sector indexes + FREE sectors to max # + EndOfChain
                for (int j = 0; j < xbat_count; j++)
                {
                    limit = Math.Min(block_count - block_index,
                                     max_entries_per_block);
                    byte[] data   = raw_block_list.Remove(chain_index).Data;
                    int    offset = 0;

                    for (int k = 0; k < limit; k++)
                    {
                        blocks[block_index++] =
                            (RawDataBlock)raw_block_list.Remove(LittleEndian.GetInt(data, offset));
                        offset += LittleEndianConsts.INT_SIZE;
                    }
                    chain_index = LittleEndian.GetInt(data, chain_index_offset);
                    if (chain_index == POIFSConstants.END_OF_CHAIN)
                    {
                        break;
                    }
                }
            }
            if (block_index != block_count)
            {
                throw new IOException("Could not find all blocks");
            }

            // now that we have all of the raw data blocks, go through and
            // create the indices
            SetEntries((ListManagedBlock[])blocks, raw_block_list);
        }