mirror of
https://github.com/AppleCommander/AppleCommander.git
synced 2024-12-22 08:30:35 +00:00
Implement directory creation in ProDOS
Side effect: opened up the previously private 'Name' class in ui; this simplifies directory handling elsewhere, as it automatically creates a directory structure to a pathed file.
This commit is contained in:
parent
01fd44f8fd
commit
87eca0095c
@ -47,7 +47,7 @@ public interface DirectoryEntry {
|
||||
/**
|
||||
* Create a new DirectoryEntry.
|
||||
*/
|
||||
public DirectoryEntry createDirectory() throws DiskFullException;
|
||||
public DirectoryEntry createDirectory(String name) throws DiskFullException;
|
||||
|
||||
/**
|
||||
* Identify if additional directories can be created. This
|
||||
|
@ -537,4 +537,12 @@ public class CpmFormatDisk extends FormattedDisk {
|
||||
public DirectoryEntry createDirectory() throws DiskFullException {
|
||||
throw new UnsupportedOperationException(textBundle.get("DirectoryCreationNotSupported")); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DirectoryEntry.
|
||||
* @see com.webcodepro.applecommander.storage.DirectoryEntry#createDirectory()
|
||||
*/
|
||||
public DirectoryEntry createDirectory(String name) throws DiskFullException {
|
||||
throw new UnsupportedOperationException(textBundle.get("DirectoryCreationNotSupported")); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
@ -745,4 +745,12 @@ public class DosFormatDisk extends FormattedDisk {
|
||||
public DirectoryEntry createDirectory() throws DiskFullException {
|
||||
throw new UnsupportedOperationException(textBundle.get("DirectoryCreationNotSupported")); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DirectoryEntry.
|
||||
* @see com.webcodepro.applecommander.storage.DirectoryEntry#createDirectory()
|
||||
*/
|
||||
public DirectoryEntry createDirectory(String name) throws DiskFullException {
|
||||
throw new UnsupportedOperationException(textBundle.get("DirectoryCreationNotSupported")); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
@ -715,4 +715,12 @@ public class GutenbergFormatDisk extends FormattedDisk {
|
||||
public DirectoryEntry createDirectory() throws DiskFullException {
|
||||
throw new UnsupportedOperationException(textBundle.get("DirectoryCreationNotSupported")); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DirectoryEntry.
|
||||
* @see com.webcodepro.applecommander.storage.DirectoryEntry#createDirectory()
|
||||
*/
|
||||
public DirectoryEntry createDirectory(String name) throws DiskFullException {
|
||||
throw new UnsupportedOperationException(textBundle.get("DirectoryCreationNotSupported")); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
@ -532,4 +532,12 @@ public class NakedosFormatDisk extends FormattedDisk {
|
||||
public DirectoryEntry createDirectory() throws DiskFullException {
|
||||
throw new UnsupportedOperationException(textBundle.get("DirectoryCreationNotSupported")); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DirectoryEntry.
|
||||
* @see com.webcodepro.applecommander.storage.DirectoryEntry#createDirectory()
|
||||
*/
|
||||
public DirectoryEntry createDirectory(String name) throws DiskFullException {
|
||||
throw new UnsupportedOperationException(textBundle.get("DirectoryCreationNotSupported")); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
@ -664,4 +664,12 @@ public class PascalFormatDisk extends FormattedDisk {
|
||||
public DirectoryEntry createDirectory() throws DiskFullException {
|
||||
throw new UnsupportedOperationException(textBundle.get("DirectoryCreationNotSupported")); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DirectoryEntry.
|
||||
* @see com.webcodepro.applecommander.storage.DirectoryEntry#createDirectory()
|
||||
*/
|
||||
public DirectoryEntry createDirectory(String name) throws DiskFullException {
|
||||
throw new UnsupportedOperationException(textBundle.get("DirectoryCreationNotSupported")); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
@ -69,14 +69,14 @@ public class ProdosCommonDirectoryHeader extends ProdosCommonEntry {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of active entries in the volume directory.
|
||||
* Get the number of active entries in the directory.
|
||||
*/
|
||||
public int getFileCount() {
|
||||
return AppleUtil.getWordValue(readFileEntry(), 0x21);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of active entries in the volume directory.
|
||||
* Set the number of active entries in the directory.
|
||||
*/
|
||||
public void setFileCount(int fileCount) {
|
||||
byte[] data = readFileEntry();
|
||||
@ -119,14 +119,14 @@ public class ProdosCommonDirectoryHeader extends ProdosCommonEntry {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total number of blocks on this volume.
|
||||
* Get the total number of blocks on this volume (only valid for volume directory block).
|
||||
*/
|
||||
public int getTotalBlocks() {
|
||||
return AppleUtil.getWordValue(readFileEntry(), 0x25);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the total number of blocks on this volume.
|
||||
* Set the total number of blocks on this volume (only valid for volume directory block).
|
||||
*/
|
||||
public void setTotalBlocks(int totalBlocks) {
|
||||
byte[] data = readFileEntry();
|
||||
|
@ -162,6 +162,20 @@ public class ProdosCommonEntry {
|
||||
setStorageType(0x03);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this is a subdirectory entry.
|
||||
*/
|
||||
public boolean isSubdirectory() {
|
||||
return getStorageType() == 0x0d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the storage type to a subdirectory entry.
|
||||
*/
|
||||
public void setSubdirectory() {
|
||||
setStorageType(0x0d);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this is a subdirectory header entry.
|
||||
*/
|
||||
|
@ -95,7 +95,7 @@ public class ProdosDirectoryEntry extends ProdosFileEntry implements DirectoryEn
|
||||
* Create a new DirectoryEntry.
|
||||
* @see com.webcodepro.applecommander.storage.DirectoryEntry#createDirectory()
|
||||
*/
|
||||
public DirectoryEntry createDirectory() throws DiskFullException {
|
||||
return getDisk().createDirectory();
|
||||
public DirectoryEntry createDirectory(String name) throws DiskFullException {
|
||||
return getDisk().createDirectory(getSubdirectoryHeader(), name);
|
||||
}
|
||||
}
|
||||
|
@ -1324,7 +1324,81 @@ public class ProdosFormatDisk extends FormattedDisk {
|
||||
* Create a new DirectoryEntry.
|
||||
* @see com.webcodepro.applecommander.storage.DirectoryEntry#createDirectory()
|
||||
*/
|
||||
public DirectoryEntry createDirectory() throws DiskFullException {
|
||||
throw new UnsupportedOperationException(textBundle.get("DirectoryCreationNotSupported")); //$NON-NLS-1$
|
||||
public DirectoryEntry createDirectory(String name) throws DiskFullException {
|
||||
return createDirectory(getVolumeHeader(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DirectoryEntry.
|
||||
* @see com.webcodepro.applecommander.storage.DirectoryEntry#createDirectory()
|
||||
*/
|
||||
public DirectoryEntry createDirectory(ProdosCommonDirectoryHeader directory, String name) throws DiskFullException {
|
||||
int blockNumber = directory.getFileEntryBlock();
|
||||
while (blockNumber != 0) {
|
||||
byte[] block = readBlock(blockNumber);
|
||||
int offset = 4;
|
||||
while (offset+ProdosCommonEntry.ENTRY_LENGTH < BLOCK_SIZE) {
|
||||
int value = AppleUtil.getUnsignedByte(block[offset]);
|
||||
if ((value & 0xf0) == 0) {
|
||||
// First, create a new block to contain our subdirectory
|
||||
byte[] volumeBitmap = readVolumeBitMap();
|
||||
int newDirBlockNumber = findFreeBlock(volumeBitmap);
|
||||
setBlockUsed(volumeBitmap, newDirBlockNumber);
|
||||
// Clean out the block - it may have been recycled, and control structures need to be gone
|
||||
byte[] cleanBlock = new byte[512];
|
||||
for (int i = 0;i<512;i++)
|
||||
cleanBlock[i] = 0;
|
||||
writeBlock(newDirBlockNumber, cleanBlock);
|
||||
writeVolumeBitMap(volumeBitmap);
|
||||
ProdosSubdirectoryHeader newHeader = new ProdosSubdirectoryHeader(this, newDirBlockNumber);
|
||||
ProdosFileEntry subdirEntry = (ProdosFileEntry)createFile(newHeader);
|
||||
subdirEntry.setFilename(name);
|
||||
newHeader.setHousekeeping();
|
||||
newHeader.setCreationDate(new Date());
|
||||
newHeader.setParentPointer(blockNumber);
|
||||
// Now, add an entry for this subdirectory
|
||||
ProdosDirectoryEntry fileEntry =
|
||||
new ProdosDirectoryEntry(this, blockNumber, offset, newHeader);
|
||||
fileEntry.setBlocksUsed(1); // Mark ourselves as the one block in use in this new subdirectory
|
||||
fileEntry.setEofPosition(BLOCK_SIZE);
|
||||
fileEntry.setKeyPointer(newDirBlockNumber);
|
||||
fileEntry.setCreationDate(new Date());
|
||||
fileEntry.setLastModificationDate(new Date());
|
||||
fileEntry.setProdosVersion(0);
|
||||
fileEntry.setMinimumProdosVersion(0);
|
||||
fileEntry.setCanDestroy(true);
|
||||
fileEntry.setCanRead(true);
|
||||
fileEntry.setCanRename(true);
|
||||
fileEntry.setCanWrite(true);
|
||||
fileEntry.setSubdirectory();
|
||||
fileEntry.setHeaderPointer(blockNumber);
|
||||
fileEntry.setFilename(name);
|
||||
fileEntry.setFiletype(0x0f); // Filetype = subdirectory
|
||||
directory.incrementFileCount();
|
||||
return fileEntry;
|
||||
}
|
||||
offset+= ProdosCommonEntry.ENTRY_LENGTH;
|
||||
}
|
||||
int nextBlockNumber = AppleUtil.getWordValue(block, NEXT_BLOCK_POINTER);
|
||||
if (nextBlockNumber == 0 && directory instanceof ProdosSubdirectoryHeader) {
|
||||
byte[] volumeBitmap = readVolumeBitMap();
|
||||
nextBlockNumber = findFreeBlock(volumeBitmap);
|
||||
setBlockUsed(volumeBitmap, nextBlockNumber);
|
||||
writeVolumeBitMap(volumeBitmap);
|
||||
byte[] oldBlock = readBlock(blockNumber);
|
||||
AppleUtil.setWordValue(oldBlock, NEXT_BLOCK_POINTER, nextBlockNumber);
|
||||
writeBlock(blockNumber, oldBlock);
|
||||
byte[] nextBlock = new byte[BLOCK_SIZE];
|
||||
AppleUtil.setWordValue(nextBlock, PREV_BLOCK_POINTER, blockNumber);
|
||||
writeBlock(nextBlockNumber, nextBlock);
|
||||
ProdosSubdirectoryHeader header = (ProdosSubdirectoryHeader) directory;
|
||||
int blockCount = header.getProdosDirectoryEntry().getBlocksUsed();
|
||||
blockCount++;
|
||||
header.getProdosDirectoryEntry().setBlocksUsed(blockCount);
|
||||
header.getProdosDirectoryEntry().setEofPosition(blockCount * BLOCK_SIZE);
|
||||
}
|
||||
blockNumber = nextBlockNumber;
|
||||
}
|
||||
throw new DiskFullException(textBundle.get("ProdosFormatDisk.UnableToAllocateSpaceError")); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ package com.webcodepro.applecommander.storage.os.prodos;
|
||||
import com.webcodepro.applecommander.util.AppleUtil;
|
||||
|
||||
/**
|
||||
* Provides commone subdirectory attributes.
|
||||
* Provides common subdirectory attributes.
|
||||
* <p>
|
||||
* Date created: Oct 5, 2002 11:17:57 PM
|
||||
* @author Rob Greene
|
||||
@ -52,6 +52,15 @@ public class ProdosSubdirectoryHeader extends ProdosCommonDirectoryHeader {
|
||||
return AppleUtil.getWordValue(readFileEntry(), 0x23);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the block number of the parent directory which contains the
|
||||
* file entry for this subdirectory.
|
||||
*/
|
||||
public void setParentPointer(int block) {
|
||||
byte[] data = readFileEntry();
|
||||
AppleUtil.setWordValue(data, 0x23, block);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of the file entry within the parent block.
|
||||
*/
|
||||
@ -79,4 +88,17 @@ public class ProdosSubdirectoryHeader extends ProdosCommonDirectoryHeader {
|
||||
public ProdosDirectoryEntry getProdosDirectoryEntry() {
|
||||
return directoryEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up some housekeeping bits
|
||||
*/
|
||||
public void setHousekeeping() {
|
||||
byte[] data = readFileEntry();
|
||||
data[0x00] = (byte) (0xe0 | (data[0x00] & 0x0f)); // Subdirectories have the high nibble set to 0x0e
|
||||
data[0x10] = 0x75; // Reserved - must be $75
|
||||
data[0x1f] = (byte) ENTRY_LENGTH;
|
||||
data[0x20] = 0x0d;
|
||||
AppleUtil.setWordValue(data, 0x21, 0); // Set file count to zero
|
||||
writeFileEntry(data);
|
||||
}
|
||||
}
|
||||
|
@ -509,4 +509,12 @@ public class RdosFormatDisk extends FormattedDisk {
|
||||
public DirectoryEntry createDirectory() throws DiskFullException {
|
||||
throw new UnsupportedOperationException(textBundle.get("DirectoryCreationNotSupported")); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DirectoryEntry.
|
||||
* @see com.webcodepro.applecommander.storage.DirectoryEntry#createDirectory()
|
||||
*/
|
||||
public DirectoryEntry createDirectory(String name) throws DiskFullException {
|
||||
throw new UnsupportedOperationException(textBundle.get("DirectoryCreationNotSupported")); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
@ -574,7 +574,7 @@ public class ac {
|
||||
"CommandLineHelp", AppleCommander.VERSION)); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private static class Name {
|
||||
public static class Name {
|
||||
private String fullName;
|
||||
private String name;
|
||||
private String[] path;
|
||||
@ -616,17 +616,31 @@ public class ac {
|
||||
return formattedDisk.createFile();
|
||||
}
|
||||
List files = formattedDisk.getFiles();
|
||||
DirectoryEntry dir = null;
|
||||
DirectoryEntry dir = null, parentDir = null;
|
||||
for (int i = 0; i < path.length - 1; i++) {
|
||||
String dirName = path[i];
|
||||
dir = null;
|
||||
for (int j = 0; j < files.size(); j++) {
|
||||
FileEntry entry = (FileEntry) files.get(j);
|
||||
String entryName = entry.getFilename();
|
||||
if (entry.isDirectory() && dirName.equalsIgnoreCase(entryName)) {
|
||||
if (!entry.isDeleted() && entry.isDirectory() && dirName.equalsIgnoreCase(entryName)) {
|
||||
dir = (DirectoryEntry) entry;
|
||||
parentDir = dir;
|
||||
files = dir.getFiles();
|
||||
}
|
||||
}
|
||||
if (dir == null) {
|
||||
if (parentDir != null) {
|
||||
// If there's a parent directory in the mix, add
|
||||
// the new child directory to that.
|
||||
dir = parentDir.createDirectory(dirName);
|
||||
parentDir = dir;
|
||||
} else {
|
||||
// Add the directory to the root of the filesystem
|
||||
dir = formattedDisk.createDirectory(dirName);
|
||||
parentDir = dir;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dir != null) {
|
||||
return dir.createFile();
|
||||
|
@ -25,6 +25,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import com.webcodepro.applecommander.storage.Disk;
|
||||
import com.webcodepro.applecommander.storage.FileEntry;
|
||||
import com.webcodepro.applecommander.storage.FormattedDisk;
|
||||
import com.webcodepro.applecommander.storage.StorageBundle;
|
||||
import com.webcodepro.applecommander.storage.os.prodos.ProdosFileEntry;
|
||||
@ -32,6 +33,7 @@ import com.webcodepro.applecommander.storage.os.prodos.ProdosFormatDisk;
|
||||
import com.webcodepro.applecommander.storage.physical.ByteArrayImageLayout;
|
||||
import com.webcodepro.applecommander.storage.physical.ImageOrder;
|
||||
import com.webcodepro.applecommander.storage.physical.ProdosOrder;
|
||||
import com.webcodepro.applecommander.ui.ac.Name;
|
||||
import com.webcodepro.applecommander.util.TextBundle;
|
||||
import com.webcodepro.shrinkit.io.LittleEndianByteInputStream;
|
||||
|
||||
@ -118,7 +120,8 @@ public class Utilities
|
||||
{
|
||||
if (dataFork != null)
|
||||
{
|
||||
newFile = (ProdosFileEntry) pdDisk.createFile();
|
||||
Name name = new Name(b.getFilename());
|
||||
newFile = (ProdosFileEntry)name.createEntry(pdDisk);
|
||||
if (newFile != null)
|
||||
{
|
||||
if (resourceFork != null)
|
||||
|
Loading…
Reference in New Issue
Block a user