Bug found by Ivan Drucker: zero length data forks (but positive length resource forks) were being silently ignored.

This commit is contained in:
2013-11-19 04:06:58 +00:00
parent 11805cd8b3
commit 8e277d98e8
2 changed files with 29 additions and 20 deletions

View File

@ -730,9 +730,14 @@ public class ProdosFormatDisk extends FormattedDisk {
protected void setFileData(ProdosFileEntry fileEntry, byte[] dataFork, byte[] resourceFork) protected void setFileData(ProdosFileEntry fileEntry, byte[] dataFork, byte[] resourceFork)
throws DiskFullException { 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! // compute free space and see if the data will fit!
int numberOfDataBlocks = (dataFork.length + BLOCK_SIZE - 1) / BLOCK_SIZE + int numberOfDataBlocks = (dataLength + BLOCK_SIZE - 1) / BLOCK_SIZE +
(resourceFork.length + BLOCK_SIZE - 1) / BLOCK_SIZE; (resourceLength + BLOCK_SIZE - 1) / BLOCK_SIZE;
int numberOfBlocks = numberOfDataBlocks; int numberOfBlocks = numberOfDataBlocks;
if (numberOfBlocks > 1) { if (numberOfBlocks > 1) {
numberOfBlocks+= ((numberOfDataBlocks-1) / 256) + 1; // that's 128K numberOfBlocks+= ((numberOfDataBlocks-1) / 256) + 1; // that's 128K
@ -762,13 +767,13 @@ public class ProdosFormatDisk extends FormattedDisk {
byte[] masterIndexBlockData = new byte[BLOCK_SIZE]; byte[] masterIndexBlockData = new byte[BLOCK_SIZE];
int offset = 0; int offset = 0;
numberOfDataBlocks = (dataFork.length + BLOCK_SIZE - 1) / BLOCK_SIZE ; numberOfDataBlocks = (dataLength + BLOCK_SIZE - 1) / BLOCK_SIZE ;
while (offset < dataFork.length) { while (offset < dataLength) {
blockNumber = findFreeBlock(bitmap); blockNumber = findFreeBlock(bitmap);
setBlockUsed(bitmap, blockNumber); setBlockUsed(bitmap, blockNumber);
blockCount++; blockCount++;
byte[] blockData = new byte[BLOCK_SIZE]; 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); System.arraycopy(dataFork,offset,blockData,0,length);
writeBlock(blockNumber, blockData); writeBlock(blockNumber, blockData);
if (numberOfDataBlocks > 1) { if (numberOfDataBlocks > 1) {
@ -806,8 +811,8 @@ public class ProdosFormatDisk extends FormattedDisk {
offset+= BLOCK_SIZE; offset+= BLOCK_SIZE;
} }
AppleUtil.setWordValue(extendedKeyBlockData,0x03,numberOfDataBlocks); // Set the number of blocks used AppleUtil.setWordValue(extendedKeyBlockData,0x03,numberOfDataBlocks); // Set the number of blocks used
AppleUtil.set3ByteValue(extendedKeyBlockData,0x05, dataFork.length); // Set the number of bytes used AppleUtil.set3ByteValue(extendedKeyBlockData,0x05, dataLength); // Set the number of bytes used
if (numberOfDataBlocks == 1) { if ((numberOfDataBlocks == 0) || (numberOfDataBlocks == 1)) {
extendedKeyBlockData[0] = 1; // Set the seedling ProDOS storage type extendedKeyBlockData[0] = 1; // Set the seedling ProDOS storage type
AppleUtil.setWordValue(extendedKeyBlockData,1,blockNumber); // Set the master block number AppleUtil.setWordValue(extendedKeyBlockData,1,blockNumber); // Set the master block number
} else if (numberOfDataBlocks <= 256) { } else if (numberOfDataBlocks <= 256) {
@ -826,13 +831,13 @@ public class ProdosFormatDisk extends FormattedDisk {
indexBlockNumber = 0; indexBlockNumber = 0;
indexBlockData = null; indexBlockData = null;
masterIndexBlockNumber = 0; masterIndexBlockNumber = 0;
numberOfDataBlocks = (resourceFork.length + BLOCK_SIZE - 1) / BLOCK_SIZE; numberOfDataBlocks = (resourceLength + BLOCK_SIZE - 1) / BLOCK_SIZE;
while (offset < resourceFork.length) { while (offset < resourceLength) {
if (blockCount > 0) blockNumber = findFreeBlock(bitmap); if (blockCount > 0) blockNumber = findFreeBlock(bitmap);
setBlockUsed(bitmap, blockNumber); setBlockUsed(bitmap, blockNumber);
blockCount++; blockCount++;
byte[] blockData = new byte[BLOCK_SIZE]; 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); System.arraycopy(resourceFork,offset,blockData,0,length);
writeBlock(blockNumber, blockData); writeBlock(blockNumber, blockData);
if (numberOfDataBlocks > 1) { if (numberOfDataBlocks > 1) {
@ -870,8 +875,8 @@ public class ProdosFormatDisk extends FormattedDisk {
offset+= BLOCK_SIZE; offset+= BLOCK_SIZE;
} }
AppleUtil.setWordValue(extendedKeyBlockData,0x103,numberOfDataBlocks); // Set the number of blocks used AppleUtil.setWordValue(extendedKeyBlockData,0x103,numberOfDataBlocks); // Set the number of blocks used
AppleUtil.set3ByteValue(extendedKeyBlockData,0x105, resourceFork.length); // Set the number of bytes used AppleUtil.set3ByteValue(extendedKeyBlockData,0x105, resourceLength); // Set the number of bytes used
if (numberOfDataBlocks == 1) { if ((numberOfDataBlocks == 0) || (numberOfDataBlocks == 1)) {
extendedKeyBlockData[0x100] = 1; // Set the seedling ProDOS storage type extendedKeyBlockData[0x100] = 1; // Set the seedling ProDOS storage type
AppleUtil.setWordValue(extendedKeyBlockData,0x101,blockNumber); // Set the master block number AppleUtil.setWordValue(extendedKeyBlockData,0x101,blockNumber); // Set the master block number
} else if (numberOfDataBlocks <= 256) { } else if (numberOfDataBlocks <= 256) {
@ -888,7 +893,7 @@ public class ProdosFormatDisk extends FormattedDisk {
fileEntry.setKeyPointer(extendedKeyBlockNumber); fileEntry.setKeyPointer(extendedKeyBlockNumber);
fileEntry.setBlocksUsed(blockCount); fileEntry.setBlocksUsed(blockCount);
fileEntry.setEofPosition(dataFork.length+resourceFork.length); fileEntry.setEofPosition(dataLength+resourceLength);
fileEntry.setLastModificationDate(new Date()); fileEntry.setLastModificationDate(new Date());
writeVolumeBitMap(bitmap); writeVolumeBitMap(bitmap);
} }

View File

@ -135,7 +135,7 @@ public class Utilities
} }
try try
{ {
if (dataFork != null) if ((dataFork != null) || (resourceFork != null))
{ {
Name name = new Name(b.getFilename()); Name name = new Name(b.getFilename());
newFile = (ProdosFileEntry)name.createEntry(pdDisk); newFile = (ProdosFileEntry)name.createEntry(pdDisk);
@ -182,15 +182,19 @@ public class Utilities
* *
* Reads the data from a thread * Reads the data from a thread
* *
* @returns byte[] buffer * @returns byte[] buffer, possibly null
*/ */
public static byte[] readThread(ThreadRecord thread) throws IOException public static byte[] readThread(ThreadRecord thread) throws IOException
{ {
thread.readThreadData(new LittleEndianByteInputStream(thread.getRawInputStream())); byte[] buffer = null;
InputStream fis = thread.getInputStream(); if (thread != null)
byte[] buffer = new byte[(int) (thread.getThreadEof())]; {
fis.read(buffer, 0, buffer.length); thread.readThreadData(new LittleEndianByteInputStream(thread.getRawInputStream()));
fis.close(); InputStream fis = thread.getInputStream();
buffer = new byte[(int) (thread.getThreadEof())];
fis.read(buffer, 0, buffer.length);
fis.close();
}
return buffer; return buffer;
} }
} }