/** Constructor, intended for writing */ public NPOIFSFileSystem() { this(true); // Mark us as having a single empty BAT at offset 0 _header.setBATCount(1); _header.setBATArray(new int[] {0}); _bat_blocks.add(BATBlock.createEmptyBATBlock(bigBlockSize, false)); setNextBlock(0, POIFSConstants.FAT_SECTOR_BLOCK); // Now associate the properties with the empty block _property_table.setStartBlock(1); setNextBlock(1, POIFSConstants.END_OF_CHAIN); }
/** * 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. */ @Override protected int getFreeBlock() throws IOException { // First up, do we have any spare ones? int offset = 0; for (int i = 0; i < _bat_blocks.size(); i++) { int numSectors = bigBlockSize.getBATEntriesPerBlock(); // Check this one BATBlock bat = _bat_blocks.get(i); if (bat.hasFreeSectors()) { // Claim one of them and return it for (int j = 0; j < numSectors; j++) { int batValue = bat.getValueAt(j); if (batValue == POIFSConstants.UNUSED_BLOCK) { // Bingo return offset + j; } } } // Move onto the next BAT offset += numSectors; } // If we get here, then there aren't any free sectors // in any of the BATs, so we need another BAT BATBlock bat = createBAT(offset, true); bat.setValueAt(0, POIFSConstants.FAT_SECTOR_BLOCK); _bat_blocks.add(bat); // Now store a reference to the BAT in the required place if (_header.getBATCount() >= 109) { // Needs to come from an XBAT BATBlock xbat = null; for (BATBlock x : _xbat_blocks) { if (x.hasFreeSectors()) { xbat = x; break; } } if (xbat == null) { // Oh joy, we need a new XBAT too... xbat = createBAT(offset + 1, false); xbat.setValueAt(0, offset); bat.setValueAt(1, POIFSConstants.DIFAT_SECTOR_BLOCK); // Will go one place higher as XBAT added in offset++; // Chain it if (_xbat_blocks.size() == 0) { _header.setXBATStart(offset); } else { _xbat_blocks .get(_xbat_blocks.size() - 1) .setValueAt(bigBlockSize.getXBATEntriesPerBlock(), offset); } _xbat_blocks.add(xbat); _header.setXBATCount(_xbat_blocks.size()); } // Allocate us in the XBAT for (int i = 0; i < bigBlockSize.getXBATEntriesPerBlock(); i++) { if (xbat.getValueAt(i) == POIFSConstants.UNUSED_BLOCK) { xbat.setValueAt(i, offset); } } } else { // Store us in the header int[] newBATs = new int[_header.getBATCount() + 1]; System.arraycopy(_header.getBATArray(), 0, newBATs, 0, newBATs.length - 1); newBATs[newBATs.length - 1] = offset; _header.setBATArray(newBATs); } _header.setBATCount(_bat_blocks.size()); // The current offset stores us, but the next one is free return offset + 1; }