/// <summary> /// Initializes a new instance of the <see cref="SmallBlockTableWriter"/> class. /// </summary> /// <param name="documents">a IList of POIFSDocument instances</param> /// <param name="root">the Filesystem's root property</param> public SmallBlockTableWriter(POIFSBigBlockSize bigBlockSize, IList documents, RootProperty root) { _sbat = new BlockAllocationTableWriter(bigBlockSize); _small_blocks = new ArrayList(); _root = root; IEnumerator iter = documents.GetEnumerator(); while (iter.MoveNext()) { POIFSDocument doc = ( POIFSDocument ) iter.Current; BlockWritable[] blocks = doc.SmallBlocks; if (blocks.Length != 0) { doc.StartBlock=_sbat.AllocateSpace(blocks.Length); for (int j = 0; j < blocks.Length; j++) { _small_blocks.Add(blocks[ j ]); } } else { doc.StartBlock=POIFSConstants.END_OF_CHAIN; } } _sbat.SimpleCreateBlocks(); _root.Size=_small_blocks.Count; _big_block_count = SmallDocumentBlock.Fill(bigBlockSize, _small_blocks); }
/** * Has our in-memory objects write their state * to their backing blocks */ private void syncWithDataSource() { // Mini Stream + SBATs first, as mini-stream details have // to be stored in the Root Property _mini_store.SyncWithDataSource(); // Properties NPOIFSStream propStream = new NPOIFSStream(this, _header.PropertyStart); _property_table.PreWrite(); _property_table.Write(propStream); // _header.setPropertyStart has been updated on write ... // HeaderBlock HeaderBlockWriter hbw = new HeaderBlockWriter(_header); hbw.WriteBlock(GetBlockAt(-1)); // BATs foreach (BATBlock bat in _bat_blocks) { ByteBuffer block = GetBlockAt(bat.OurBlockIndex); //byte[] block = GetBlockAt(bat.OurBlockIndex); BlockAllocationTableWriter.WriteBlock(bat, block); } // XBats foreach (BATBlock bat in _xbat_blocks) { ByteBuffer block = GetBlockAt(bat.OurBlockIndex); BlockAllocationTableWriter.WriteBlock(bat, block); } }
/** * Writes the SBATs to their backing blocks */ public void SyncWithDataSource() { foreach (BATBlock sbat in _sbat_blocks) { ByteBuffer block = _filesystem.GetBlockAt(sbat.OurBlockIndex); BlockAllocationTableWriter.WriteBlock(sbat, block); } }
public static void VerifyBlocksCreated(BlockAllocationTableWriter table, int count) { MemoryStream stream = new MemoryStream(); table.WriteBlocks(stream); byte[] output = stream.ToArray(); Assert.AreEqual(count * 512, output.Length); }
public void TestWritingConstructor() { ArrayList documents = new ArrayList(); documents.Add( new POIFSDocument( "doc340", new MemoryStream(new byte[340]))); documents.Add( new POIFSDocument( "doc5000", new MemoryStream(new byte[5000]))); documents .Add(new POIFSDocument("doc0", new MemoryStream(new byte[0]))); documents .Add(new POIFSDocument("doc1", new MemoryStream(new byte[1]))); documents .Add(new POIFSDocument("doc2", new MemoryStream(new byte[2]))); documents .Add(new POIFSDocument("doc3", new MemoryStream(new byte[3]))); documents .Add(new POIFSDocument("doc4", new MemoryStream(new byte[4]))); documents .Add(new POIFSDocument("doc5", new MemoryStream(new byte[5]))); documents .Add(new POIFSDocument("doc6", new MemoryStream(new byte[6]))); documents .Add(new POIFSDocument("doc7", new MemoryStream(new byte[7]))); documents .Add(new POIFSDocument("doc8", new MemoryStream(new byte[8]))); documents .Add(new POIFSDocument("doc9", new MemoryStream(new byte[9]))); HeaderBlock header = new HeaderBlock(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS); RootProperty root = new PropertyTable(header).Root; SmallBlockTableWriter sbtw = new SmallBlockTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, documents, root); BlockAllocationTableWriter bat = sbtw.SBAT; // 15 small blocks: 6 for doc340, 0 for doc5000 (too big), 0 // for doc0 (no storage needed), 1 each for doc1 through doc9 Assert.AreEqual(15 * 64, root.Size); // 15 small blocks rounds up to 2 big blocks Assert.AreEqual(2, sbtw.CountBlocks); int start_block = 1000 + root.StartBlock; sbtw.StartBlock = start_block; Assert.AreEqual(start_block, root.StartBlock); }
public void TestAllocateSpace() { BlockAllocationTableWriter table = new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS); int[] blockSizes = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int expectedIndex = 0; for (int i = 0; i < blockSizes.Length; i++) { Assert.AreEqual(expectedIndex, table.AllocateSpace(blockSizes[i])); expectedIndex += blockSizes[i]; } }
public void TestProduct() { BlockAllocationTableWriter table = new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS); for (int i = 1; i <= 22; i++) { table.AllocateSpace(i); } table.CreateBlocks(); MemoryStream stream = new MemoryStream(); table.WriteBlocks(stream); byte[] output = stream.ToArray(); Assert.AreEqual(1024, output.Length); byte[] expected = new byte[1024]; for (int i = 0; i < expected.Length; i++) { expected[i] = (byte)0xFF; } int offset = 0; int blockIndex = 1; for (int i = 1; i <= 22; i++) { int limit = i - 1; for (int j = 0; j < limit; j++) { LittleEndian.PutInt(expected, offset, blockIndex++); offset += LittleEndianConsts.INT_SIZE; } LittleEndian.PutInt(expected, offset, POIFSConstants.END_OF_CHAIN); offset += 4; blockIndex++; } LittleEndian.PutInt(expected, offset, blockIndex++); offset += LittleEndianConsts.INT_SIZE; LittleEndian.PutInt(expected, offset, POIFSConstants.END_OF_CHAIN); for (int i = 0; i < expected.Length; i++) { Assert.AreEqual(expected[i], output[i], "At offset " + i); } }
public void TestProduct() { BlockAllocationTableWriter table = new BlockAllocationTableWriter(); for (int k = 1; k <= 22; k++) { table.AllocateSpace(k); } table.CreateBlocks(); MemoryStream stream = new MemoryStream(); table.WriteBlocks(stream); byte[] output = stream.ToArray(); Assert.AreEqual(1024, output.Length); byte[] expected = new byte[1024]; for (int i = 0; i < expected.Length; i++) { expected[i] = (byte)0xFF; } int offset = 0; int block_index = 1; for (int k = 1; k <= 22; k++) { int limit = k - 1; for (int j = 0; j < limit; j++) { LittleEndian.PutInt(expected, offset, block_index++); offset += LittleEndianConstants.INT_SIZE; } LittleEndian.PutInt(expected, offset, POIFSConstants.END_OF_CHAIN); offset += 4; block_index++; } // Add BAT block indices LittleEndian.PutInt(expected, offset, block_index++); offset += LittleEndianConstants.INT_SIZE; LittleEndian.PutInt(expected, offset, POIFSConstants.END_OF_CHAIN); for (int k = 0; k < expected.Length; k++) { Assert.AreEqual(expected[k], output[k], "At offset " + k); } }
public void TestAllocateSpace() { BlockAllocationTableWriter table = new BlockAllocationTableWriter(); int[] blockSizes = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int expectedIndex = 0; for (int j = 0; j < blockSizes.Length; j++) { Assert.AreEqual(expectedIndex, table.AllocateSpace(blockSizes[j])); expectedIndex += blockSizes[j]; } }
public void TestCreateBlocks() { BlockAllocationTableWriter table = new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS); table.AllocateSpace(127); table.CreateBlocks(); VerifyBlocksCreated(table, 1); table = new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS); table.AllocateSpace(128); table.CreateBlocks(); VerifyBlocksCreated(table, 2); table = new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS); table.AllocateSpace(254); table.CreateBlocks(); VerifyBlocksCreated(table, 2); table = new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS); table.AllocateSpace(255); table.CreateBlocks(); VerifyBlocksCreated(table, 3); table = new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS); table.AllocateSpace(13843); table.CreateBlocks(); VerifyBlocksCreated(table, 109); table = new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS); table.AllocateSpace(13844); table.CreateBlocks(); VerifyBlocksCreated(table, 110); table = new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS); table.AllocateSpace(13969); table.CreateBlocks(); VerifyBlocksCreated(table, 110); table = new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS); table.AllocateSpace(13970); table.CreateBlocks(); VerifyBlocksCreated(table, 111); }
/// <summary> /// Writes the SBATs to their backing blocks, and updates /// the mini-stream size in the properties. Stream size is /// based on full blocks used, not the data within the streams /// </summary> public void SyncWithDataSource() { int blocksUsed = 0; foreach (BATBlock sbat in _sbat_blocks) { ByteBuffer block = _filesystem.GetBlockAt(sbat.OurBlockIndex); BlockAllocationTableWriter.WriteBlock(sbat, block); if (!sbat.HasFreeSectors) { blocksUsed += _filesystem.GetBigBlockSizeDetails().GetBATEntriesPerBlock(); } else { blocksUsed += sbat.GetUsedSectors(false); } } // Set the size on the root in terms of the number of SBAT blocks // RootProperty.setSize does the sbat -> bytes conversion for us _filesystem.PropertyTable.Root.Size = (blocksUsed); }
/** * Has our in-memory objects write their state * to their backing blocks */ private void syncWithDataSource() { // HeaderBlock HeaderBlockWriter hbw = new HeaderBlockWriter(_header); hbw.WriteBlock(GetBlockAt(-1)); // BATs foreach (BATBlock bat in _bat_blocks) { ByteBuffer block = GetBlockAt(bat.OurBlockIndex); //byte[] block = GetBlockAt(bat.OurBlockIndex); BlockAllocationTableWriter.WriteBlock(bat, block); } // SBATs _mini_store.SyncWithDataSource(); // Properties _property_table.Write(new NPOIFSStream(this, _header.PropertyStart) ); }
public void TestCreateBlocks() { BlockAllocationTableWriter table = new BlockAllocationTableWriter(); table.AllocateSpace(127); table.CreateBlocks(); verifyBlocksCreated(table, 1); table = new BlockAllocationTableWriter(); table.AllocateSpace(128); table.CreateBlocks(); verifyBlocksCreated(table, 2); table = new BlockAllocationTableWriter(); table.AllocateSpace(254); table.CreateBlocks(); verifyBlocksCreated(table, 2); table = new BlockAllocationTableWriter(); table.AllocateSpace(255); table.CreateBlocks(); verifyBlocksCreated(table, 3); table = new BlockAllocationTableWriter(); table.AllocateSpace(13843); table.CreateBlocks(); verifyBlocksCreated(table, 109); table = new BlockAllocationTableWriter(); table.AllocateSpace(13844); table.CreateBlocks(); verifyBlocksCreated(table, 110); table = new BlockAllocationTableWriter(); table.AllocateSpace(13969); table.CreateBlocks(); verifyBlocksCreated(table, 110); table = new BlockAllocationTableWriter(); table.AllocateSpace(13970); table.CreateBlocks(); verifyBlocksCreated(table, 111); }
/// <summary> /// Writes the file system. /// </summary> /// <param name="stream">the OutputStream to which the filesystem will be /// written</param> public void WriteFileSystem(Stream stream) { // Get the property table Ready _property_table.PreWrite(); // Create the small block store, and the SBAT SmallBlockTableWriter sbtw = new SmallBlockTableWriter(bigBlockSize, _documents, _property_table.Root); // Create the block allocation table BlockAllocationTableWriter bat = new BlockAllocationTableWriter(bigBlockSize); // Create a list of BATManaged objects: the documents plus the // property table and the small block table List <object> bm_objects = new List <object>(); bm_objects.AddRange(_documents); bm_objects.Add(_property_table); bm_objects.Add(sbtw); bm_objects.Add(sbtw.SBAT); // walk the list, allocating space for each and assigning each // a starting block number IEnumerator iter = bm_objects.GetEnumerator(); while (iter.MoveNext()) { BATManaged bmo = ( BATManaged )iter.Current; int block_count = bmo.CountBlocks; if (block_count != 0) { bmo.StartBlock = bat.AllocateSpace(block_count); } else { // Either the BATManaged object is empty or its data // is composed of SmallBlocks; in either case, // allocating space in the BAT is inappropriate } } // allocate space for the block allocation table and take its // starting block int batStartBlock = bat.CreateBlocks(); // Get the extended block allocation table blocks HeaderBlockWriter header_block_Writer = new HeaderBlockWriter(bigBlockSize); BATBlock[] xbat_blocks = header_block_Writer.SetBATBlocks(bat.CountBlocks, batStartBlock); // Set the property table start block header_block_Writer.PropertyStart = _property_table.StartBlock; // Set the small block allocation table start block header_block_Writer.SBATStart = sbtw.SBAT.StartBlock; // Set the small block allocation table block count header_block_Writer.SBATBlockCount = sbtw.SBATBlockCount; // the header is now properly initialized. Make a list of // Writers (the header block, followed by the documents, the // property table, the small block store, the small block // allocation table, the block allocation table, and the // extended block allocation table blocks) List <object> Writers = new List <object>(); Writers.Add(header_block_Writer); Writers.AddRange(_documents); Writers.Add(_property_table); Writers.Add(sbtw); Writers.Add(sbtw.SBAT); Writers.Add(bat); for (int j = 0; j < xbat_blocks.Length; j++) { Writers.Add(xbat_blocks[j]); } // now, Write everything out iter = Writers.GetEnumerator(); while (iter.MoveNext()) { BlockWritable Writer = ( BlockWritable )iter.Current; Writer.WriteBlocks(stream); } Writers = null; iter = null; }
/// <summary> /// Writes the file system. /// </summary> /// <param name="stream">the OutputStream to which the filesystem will be /// written</param> public void WriteFileSystem(Stream stream) { // Get the property table Ready _property_table.PreWrite(); // Create the small block store, and the SBAT SmallBlockTableWriter sbtw = new SmallBlockTableWriter(bigBlockSize,_documents, _property_table.Root); // Create the block allocation table BlockAllocationTableWriter bat = new BlockAllocationTableWriter(bigBlockSize); // Create a list of BATManaged objects: the documents plus the // property table and the small block table ArrayList bm_objects = new ArrayList(); bm_objects.AddRange(_documents); bm_objects.Add(_property_table); bm_objects.Add(sbtw); bm_objects.Add(sbtw.SBAT); // walk the list, allocating space for each and assigning each // a starting block number IEnumerator iter = bm_objects.GetEnumerator(); while (iter.MoveNext()) { BATManaged bmo = ( BATManaged ) iter.Current; int block_count = bmo.CountBlocks; if (block_count != 0) { bmo.StartBlock=bat.AllocateSpace(block_count); } else { // Either the BATManaged object is empty or its data // is composed of SmallBlocks; in either case, // allocating space in the BAT is inappropriate } } // allocate space for the block allocation table and take its // starting block int batStartBlock = bat.CreateBlocks(); // Get the extended block allocation table blocks HeaderBlockWriter header_block_Writer = new HeaderBlockWriter(bigBlockSize); BATBlock[] xbat_blocks = header_block_Writer.SetBATBlocks(bat.CountBlocks, batStartBlock); // Set the property table start block header_block_Writer.PropertyStart=_property_table.StartBlock; // Set the small block allocation table start block header_block_Writer.SBATStart=sbtw.SBAT.StartBlock; // Set the small block allocation table block count header_block_Writer.SBATBlockCount=sbtw.SBATBlockCount; // the header is now properly initialized. Make a list of // Writers (the header block, followed by the documents, the // property table, the small block store, the small block // allocation table, the block allocation table, and the // extended block allocation table blocks) ArrayList Writers = new ArrayList(); Writers.Add(header_block_Writer); Writers.AddRange(_documents); Writers.Add(_property_table); Writers.Add(sbtw); Writers.Add(sbtw.SBAT); Writers.Add(bat); for (int j = 0; j < xbat_blocks.Length; j++) { Writers.Add(xbat_blocks[j]); } // now, Write everything out iter = Writers.GetEnumerator(); while (iter.MoveNext()) { BlockWritable Writer = ( BlockWritable ) iter.Current; Writer.WriteBlocks(stream); } Writers=null; iter = null; }