/* * AppleCommander - An Apple ][ image utility. * Copyright (C) 2002 by Robert Greene * robgreene at users.sourceforge.net * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.webcodepro.applecommander.storage; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * Manages a disk that is in the ProDOS format. *
* Date created: Oct 3, 2002 11:45:25 PM
* @author: Rob Greene
*/
public class ProdosFormatDisk extends FormattedDisk {
/**
* Hold on to the volume directory header.
*/
private ProdosVolumeDirectoryHeader volumeHeader;
/**
* Use this inner interface for managing the disk usage data.
* This offloads format-specific implementation to the implementing class.
*/
private class ProdosDiskUsage implements DiskUsage {
private int location = -1;
private transient byte[] data = null;
public boolean hasNext() {
return location == -1 || location < volumeHeader.getTotalBlocks() - 1;
}
public void next() {
location++;
}
/**
* Get the free setting for the bitmap at the current location.
*/
public boolean isFree() {
if (location == -1) {
throw new IllegalArgumentException("Invalid dimension for isFree! Did you call next first?");
}
if (data == null) {
data = readVolumeBitMap();
}
return isBlockFree(data, location);
}
public boolean isUsed() {
return !isFree();
}
}
/**
* Constructor for ProdosFormatDisk.
* @param filename
* @param diskImage
*/
public ProdosFormatDisk(String filename, byte[] diskImage) {
super(filename, diskImage);
volumeHeader = new ProdosVolumeDirectoryHeader(this);
}
/**
* Create a ProdosFormatDisk.
*/
public static ProdosFormatDisk[] create(String filename, String diskName, int imageSize) {
ProdosFormatDisk disk = new ProdosFormatDisk(filename, new byte[imageSize]);
disk.setDiskName(diskName);
disk.format();
return new ProdosFormatDisk[] { disk };
}
/**
* Identify the operating system format of this disk.
* @see com.webcodepro.applecommander.storage.Disk#getFormat()
*/
public String getFormat() {
return "ProDOS";
}
/**
* Retrieve a list of files.
* @see com.webcodepro.applecommander.storage.Disk#getFiles()
*/
public List getFiles() {
return getFiles(2);
}
/**
* Build a list of files, starting in the given block number.
* This works for the master as well as the subdirectories.
*/
protected List getFiles(int blockNumber) {
List files = new ArrayList();
while (blockNumber != 0) {
byte[] block = readBlock(blockNumber);
int offset = 4;
while (offset+ProdosCommonEntry.ENTRY_LENGTH < BLOCK_SIZE) {
ProdosCommonEntry tester =
new ProdosCommonEntry(this, blockNumber, offset);
if (tester.isVolumeHeader() || tester.isSubdirectoryHeader()) {
// ignore it, we've already got it
} else {
ProdosFileEntry fileEntry =
new ProdosFileEntry(this, blockNumber, offset);
files.add(fileEntry);
if (fileEntry.isDirectory()) {
int keyPointer = fileEntry.getKeyPointer();
fileEntry.setSubdirectoryHeader(
new ProdosSubdirectoryHeader(this, keyPointer));
fileEntry.setFiles(getFiles(keyPointer));
}
}
offset+= ProdosCommonEntry.ENTRY_LENGTH;
}
blockNumber = AppleUtil.getWordValue(block, 2);
}
return files;
}
/**
* Return the amount of free space in bytes.
* @see com.webcodepro.applecommander.storage.Disk#getFreeSpace()
*/
public int getFreeSpace() {
return getFreeBlocks() * BLOCK_SIZE;
}
/**
* Return the number of free blocks on the disk.
*/
public int getFreeBlocks() {
int freeBlocks = 0;
int blocksToProcess = (volumeHeader.getTotalBlocks() + 4095) / 4096;
int blockNumber = volumeHeader.getBitMapPointer();
for (int ix=0; ix