From 8e277d98e8b5cc5d28329aaee95388134c939b2e Mon Sep 17 00:00:00 2001 From: Date: Tue, 19 Nov 2013 04:06:58 +0000 Subject: [PATCH] Bug found by Ivan Drucker: zero length data forks (but positive length resource forks) were being silently ignored. --- .../storage/os/prodos/ProdosFormatDisk.java | 31 +++++++++++-------- src/com/webcodepro/shrinkit/Utilities.java | 18 ++++++----- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/com/webcodepro/applecommander/storage/os/prodos/ProdosFormatDisk.java b/src/com/webcodepro/applecommander/storage/os/prodos/ProdosFormatDisk.java index e236780..acbab8b 100644 --- a/src/com/webcodepro/applecommander/storage/os/prodos/ProdosFormatDisk.java +++ b/src/com/webcodepro/applecommander/storage/os/prodos/ProdosFormatDisk.java @@ -730,9 +730,14 @@ public class ProdosFormatDisk extends FormattedDisk { protected void setFileData(ProdosFileEntry fileEntry, byte[] dataFork, byte[] resourceFork) throws DiskFullException { + int dataLength = 0, resourceLength = 0; + if (dataFork != null) + dataLength = dataFork.length; + if (resourceFork != null) + resourceLength = resourceFork.length; // compute free space and see if the data will fit! - int numberOfDataBlocks = (dataFork.length + BLOCK_SIZE - 1) / BLOCK_SIZE + - (resourceFork.length + BLOCK_SIZE - 1) / BLOCK_SIZE; + int numberOfDataBlocks = (dataLength + BLOCK_SIZE - 1) / BLOCK_SIZE + + (resourceLength + BLOCK_SIZE - 1) / BLOCK_SIZE; int numberOfBlocks = numberOfDataBlocks; if (numberOfBlocks > 1) { numberOfBlocks+= ((numberOfDataBlocks-1) / 256) + 1; // that's 128K @@ -762,13 +767,13 @@ public class ProdosFormatDisk extends FormattedDisk { byte[] masterIndexBlockData = new byte[BLOCK_SIZE]; int offset = 0; - numberOfDataBlocks = (dataFork.length + BLOCK_SIZE - 1) / BLOCK_SIZE ; - while (offset < dataFork.length) { + numberOfDataBlocks = (dataLength + BLOCK_SIZE - 1) / BLOCK_SIZE ; + while (offset < dataLength) { blockNumber = findFreeBlock(bitmap); setBlockUsed(bitmap, blockNumber); blockCount++; byte[] blockData = new byte[BLOCK_SIZE]; - int length = Math.min(BLOCK_SIZE, dataFork.length - offset); + int length = Math.min(BLOCK_SIZE, dataLength - offset); System.arraycopy(dataFork,offset,blockData,0,length); writeBlock(blockNumber, blockData); if (numberOfDataBlocks > 1) { @@ -806,8 +811,8 @@ public class ProdosFormatDisk extends FormattedDisk { offset+= BLOCK_SIZE; } AppleUtil.setWordValue(extendedKeyBlockData,0x03,numberOfDataBlocks); // Set the number of blocks used - AppleUtil.set3ByteValue(extendedKeyBlockData,0x05, dataFork.length); // Set the number of bytes used - if (numberOfDataBlocks == 1) { + AppleUtil.set3ByteValue(extendedKeyBlockData,0x05, dataLength); // Set the number of bytes used + if ((numberOfDataBlocks == 0) || (numberOfDataBlocks == 1)) { extendedKeyBlockData[0] = 1; // Set the seedling ProDOS storage type AppleUtil.setWordValue(extendedKeyBlockData,1,blockNumber); // Set the master block number } else if (numberOfDataBlocks <= 256) { @@ -826,13 +831,13 @@ public class ProdosFormatDisk extends FormattedDisk { indexBlockNumber = 0; indexBlockData = null; masterIndexBlockNumber = 0; - numberOfDataBlocks = (resourceFork.length + BLOCK_SIZE - 1) / BLOCK_SIZE; - while (offset < resourceFork.length) { + numberOfDataBlocks = (resourceLength + BLOCK_SIZE - 1) / BLOCK_SIZE; + while (offset < resourceLength) { if (blockCount > 0) blockNumber = findFreeBlock(bitmap); setBlockUsed(bitmap, blockNumber); blockCount++; byte[] blockData = new byte[BLOCK_SIZE]; - int length = Math.min(BLOCK_SIZE, resourceFork.length - offset); + int length = Math.min(BLOCK_SIZE, resourceLength - offset); System.arraycopy(resourceFork,offset,blockData,0,length); writeBlock(blockNumber, blockData); if (numberOfDataBlocks > 1) { @@ -870,8 +875,8 @@ public class ProdosFormatDisk extends FormattedDisk { offset+= BLOCK_SIZE; } AppleUtil.setWordValue(extendedKeyBlockData,0x103,numberOfDataBlocks); // Set the number of blocks used - AppleUtil.set3ByteValue(extendedKeyBlockData,0x105, resourceFork.length); // Set the number of bytes used - if (numberOfDataBlocks == 1) { + AppleUtil.set3ByteValue(extendedKeyBlockData,0x105, resourceLength); // Set the number of bytes used + if ((numberOfDataBlocks == 0) || (numberOfDataBlocks == 1)) { extendedKeyBlockData[0x100] = 1; // Set the seedling ProDOS storage type AppleUtil.setWordValue(extendedKeyBlockData,0x101,blockNumber); // Set the master block number } else if (numberOfDataBlocks <= 256) { @@ -888,7 +893,7 @@ public class ProdosFormatDisk extends FormattedDisk { fileEntry.setKeyPointer(extendedKeyBlockNumber); fileEntry.setBlocksUsed(blockCount); - fileEntry.setEofPosition(dataFork.length+resourceFork.length); + fileEntry.setEofPosition(dataLength+resourceLength); fileEntry.setLastModificationDate(new Date()); writeVolumeBitMap(bitmap); } diff --git a/src/com/webcodepro/shrinkit/Utilities.java b/src/com/webcodepro/shrinkit/Utilities.java index 0712693..3229c87 100644 --- a/src/com/webcodepro/shrinkit/Utilities.java +++ b/src/com/webcodepro/shrinkit/Utilities.java @@ -135,7 +135,7 @@ public class Utilities } try { - if (dataFork != null) + if ((dataFork != null) || (resourceFork != null)) { Name name = new Name(b.getFilename()); newFile = (ProdosFileEntry)name.createEntry(pdDisk); @@ -182,15 +182,19 @@ public class Utilities * * Reads the data from a thread * - * @returns byte[] buffer + * @returns byte[] buffer, possibly null */ public static byte[] readThread(ThreadRecord thread) throws IOException { - thread.readThreadData(new LittleEndianByteInputStream(thread.getRawInputStream())); - InputStream fis = thread.getInputStream(); - byte[] buffer = new byte[(int) (thread.getThreadEof())]; - fis.read(buffer, 0, buffer.length); - fis.close(); + byte[] buffer = null; + if (thread != null) + { + thread.readThreadData(new LittleEndianByteInputStream(thread.getRawInputStream())); + InputStream fis = thread.getInputStream(); + buffer = new byte[(int) (thread.getThreadEof())]; + fis.read(buffer, 0, buffer.length); + fis.close(); + } return buffer; } }