Compare commits

...

7 Commits

Author SHA1 Message Date
Brian J. Bernstein b583d4a364
Merge 88e9d48a5a into 5cd97c6d35 2023-10-27 16:34:42 -07:00
Rob Greene 5cd97c6d35 Fixing recursive acx copy. #130 2023-10-27 16:37:03 -05:00
Rob Greene a375e25c66 Updating FormattedDisk API to support conversion between ProDOS file types and native file types; updated UI to use this API for imports (specifically for AppleSingle archives) in order to set the correct native file type. Fixed glitch in UI where it assumed that the file type was always found in the known list of file types. #128 2023-10-27 14:27:29 -05:00
Rob Greene 1c86c39ed2 Bumping versions identified as vulnerable. 2023-10-27 11:43:43 -05:00
Brian J. Bernstein 88e9d48a5a Updated help text for multi-op command line 2022-10-11 11:44:32 -04:00
Brian J. Bernstein 544d146d5b Updated test support for multi-op command line 2022-10-11 11:44:21 -04:00
Brian J. Bernstein 2d811de210 Changed command line parsing to allow for multiple operations in the
same JVM instance. Multiple commands are specified sequentially (e.g.
ac.sh -ptx volume.po afile afile.txt -bas volume.po bfile bfile.bas).
This required adding support for several operations to read files
instead of STDIN. However, STDIN support remains for those who want to
use it, though they need to specify '-' as the file.
2022-10-11 11:43:43 -04:00
20 changed files with 475 additions and 301 deletions

View File

@ -119,11 +119,11 @@ public class AntTask extends Task
else if (_command.equals("cc65"))
{
System.err.println("Note: 'cc65' is deprecated. Please use 'as' or 'dos' as appropriate.");
com.webcodepro.applecommander.ui.ac.putDOS(_input, _imageName, _fileName, _type);
com.webcodepro.applecommander.ui.ac.putDOS(_input, _imageName, _fileName, _type, System.in);
}
else if (_command.equals("dos"))
{
com.webcodepro.applecommander.ui.ac.putDOS(_input, _imageName, _fileName, _type);
com.webcodepro.applecommander.ui.ac.putDOS(_input, _imageName, _fileName, _type, System.in);
}
else {
com.webcodepro.applecommander.ui.ac.putAppleSingle(_imageName, _fileName,

View File

@ -26,6 +26,7 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -112,82 +113,169 @@ import io.github.applecommander.bastools.api.model.Token;
public class ac {
private static TextBundle textBundle = UiBundle.getInstance();
/**
* Finds the array index of the next operation (e.g. -bas, -ptx, -ll) from the specified
* starting point. If there is no further operation found, then a -1 is returned.
*
* @param args String array of arguments from the command line.
* @param startFrom Index to start searching from.
* @return Index of the next operation arg, or -1 if the end of the array was hit.
*/
public static int findNextOperationArg(String[] args, int startFrom) {
while (startFrom < args.length) {
// we check length>1 to make sure we're differentiating from STDIN '-'
if (args[startFrom].startsWith("-") == true && args[startFrom].length() > 1) {
return startFrom;
}
startFrom++;
}
return -1;
}
/**
* Returns an InputStream handle to either the file specified by arg or STDIN if arg is
* null, empty, or simply a '-'.
* If a file is specified to arg, then any exceptions that may get raised by attempting to open
* the file will simply get passed through since the AC's command line error handling doesn't
* really do much other than stacktrace anyway.
*
* @param arg Either a filename to open or '-' for STDIN.
* @return Handle to an InputStream ready to be pulled from.
*/
public static InputStream stdinOrFile(String arg) {
if (arg == null || arg.isEmpty() || arg.equalsIgnoreCase("-")) {
return System.in;
} else {
File f = new File(arg);
InputStream is = null;
try {
is = new FileInputStream(f);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
return is;
}
}
public static void main(String[] args) {
try {
if (args.length == 0) {
help();
} else if ("-i".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
getDiskInfo(args);
} else if ("-ls".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
showDirectory(DirectoryLister.text(FormattedDisk.FILE_DISPLAY_STANDARD), args);
} else if ("-l".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
showDirectory(DirectoryLister.text(FormattedDisk.FILE_DISPLAY_NATIVE), args);
} else if ("-ll".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
showDirectory(DirectoryLister.text(FormattedDisk.FILE_DISPLAY_DETAIL), args);
} else if ("-lsv".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
showDirectory(DirectoryLister.csv(FormattedDisk.FILE_DISPLAY_STANDARD), args);
} else if ("-lv".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
showDirectory(DirectoryLister.csv(FormattedDisk.FILE_DISPLAY_NATIVE), args);
} else if ("-llv".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
showDirectory(DirectoryLister.csv(FormattedDisk.FILE_DISPLAY_DETAIL), args);
} else if ("-lsj".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
showDirectory(DirectoryLister.json(FormattedDisk.FILE_DISPLAY_STANDARD), args);
} else if ("-lj".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
showDirectory(DirectoryLister.json(FormattedDisk.FILE_DISPLAY_NATIVE), args);
} else if ("-llj".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
showDirectory(DirectoryLister.json(FormattedDisk.FILE_DISPLAY_DETAIL), args);
} else if ("-e".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
getFile(args[1], args[2], true,
(args.length > 3 ? new PrintStream(new FileOutputStream(args[3])) : System.out));
} else if ("-x".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
getFiles(args[1], (args.length > 2 ? args[2] : ""));
} else if ("-g".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
getFile(args[1], args[2], false,
(args.length > 3 ? new PrintStream(new FileOutputStream(args[3])) : System.out));
} else if ("-p".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
putFile(args[1], new Name(args[2]), args[3],
(args.length > 4 ? args[4] : "0x2000"));
} else if ("-pt".equalsIgnoreCase(args[0])) {
putTxtFileSetHighBit(args[1], new Name(args[2]));
} else if ("-ptx".equalsIgnoreCase(args[0])) {
putTxtFileClearHighBit(args[1], new Name(args[2]));
} else if ("-d".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
deleteFile(args[1], args[2]);
} else if ("-k".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
setFileLocked(args[1], args[2], true);
} else if ("-u".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
setFileLocked(args[1], args[2], false);
} else if ("-n".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
setDiskName(args[1], args[2]);
} else if ("-cc65".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
System.err.println("Note: -cc65 is deprecated. Please use -as or -dos as appropriate.");
putDOS(args[1], new Name(args[2]), args[3]);
} else if ("-dos".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
putDOS(args[1], new Name(args[2]), args[3]);
} else if ("-as".equalsIgnoreCase(args[0])) {
putAppleSingle(args[1], args.length >= 3 ? args[2] : null);
} else if ("-geos".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
putGEOS(args[1]);
} else if ("-dos140".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
createDosDisk(args[1], Disk.APPLE_140KB_DISK);
} else if ("-pas140".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
createPasDisk(args[1], args[2], Disk.APPLE_140KB_DISK);
} else if ("-pas800".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
createPasDisk(args[1], args[2], Disk.APPLE_800KB_DISK);
} else if ("-pro140".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
createProDisk(args[1], args[2], Disk.APPLE_140KB_DISK);
} else if ("-pro800".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
createProDisk(args[1], args[2], Disk.APPLE_800KB_DISK);
} else if ("-convert".equalsIgnoreCase(args[0])) { //$NON-NLS-1$
if (args.length > 3)
convert(args[1], args[2], Integer.parseInt(args[3]));
else
convert(args[1], args[2]);
} else if ("-bas".equalsIgnoreCase(args[0])) {
putAppleSoft(args[1], args[2]);
} else {
help();
}
int argPtr = 0;
while (argPtr < args.length && argPtr > -1) {
InputStream inputStream = null;
int nextArg = findNextOperationArg(args, argPtr + 1);
if (nextArg == -1) {
nextArg = args.length;
}
String[] trimmedArgs = Arrays.copyOfRange(args, argPtr, nextArg);
if ("-i".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
getDiskInfo(trimmedArgs);
} else if ("-ls".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
showDirectory(DirectoryLister.text(FormattedDisk.FILE_DISPLAY_STANDARD), trimmedArgs);
} else if ("-l".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
showDirectory(DirectoryLister.text(FormattedDisk.FILE_DISPLAY_NATIVE), trimmedArgs);
} else if ("-ll".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
showDirectory(DirectoryLister.text(FormattedDisk.FILE_DISPLAY_DETAIL), trimmedArgs);
} else if ("-lsv".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
showDirectory(DirectoryLister.csv(FormattedDisk.FILE_DISPLAY_STANDARD), trimmedArgs);
} else if ("-lv".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
showDirectory(DirectoryLister.csv(FormattedDisk.FILE_DISPLAY_NATIVE), trimmedArgs);
} else if ("-llv".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
showDirectory(DirectoryLister.csv(FormattedDisk.FILE_DISPLAY_DETAIL), trimmedArgs);
} else if ("-lsj".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
showDirectory(DirectoryLister.json(FormattedDisk.FILE_DISPLAY_STANDARD), trimmedArgs);
} else if ("-lj".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
showDirectory(DirectoryLister.json(FormattedDisk.FILE_DISPLAY_NATIVE), trimmedArgs);
} else if ("-llj".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
showDirectory(DirectoryLister.json(FormattedDisk.FILE_DISPLAY_DETAIL), trimmedArgs);
} else if ("-e".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
getFile(trimmedArgs[1], trimmedArgs[2], true,
(trimmedArgs.length > 3 ? new PrintStream(new FileOutputStream(trimmedArgs[3])) : System.out));
} else if ("-x".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
getFiles(trimmedArgs[1], (args.length > 2 ? trimmedArgs[2] : ""));
} else if ("-g".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
getFile(trimmedArgs[1], trimmedArgs[2], false,
(trimmedArgs.length > 3 ? new PrintStream(new FileOutputStream(trimmedArgs[3])) : System.out));
} else if ("-p".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
String addr = "0x2000";
if (trimmedArgs.length > 5) {
addr = trimmedArgs[4];
inputStream = stdinOrFile(trimmedArgs[5]);
} else {
inputStream = stdinOrFile(trimmedArgs[4]);
}
putFile(trimmedArgs[1], new Name(trimmedArgs[2]), trimmedArgs[3], addr, inputStream);
} else if ("-pt".equalsIgnoreCase(trimmedArgs[0])) {
inputStream = stdinOrFile(trimmedArgs[3]);
putTxtFileSetHighBit(trimmedArgs[1], new Name(trimmedArgs[2]), inputStream);
} else if ("-ptx".equalsIgnoreCase(trimmedArgs[0])) {
inputStream = stdinOrFile(trimmedArgs[3]);
putTxtFileClearHighBit(trimmedArgs[1], new Name(trimmedArgs[2]), inputStream);
} else if ("-d".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
deleteFile(trimmedArgs[1], trimmedArgs[2]);
} else if ("-k".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
setFileLocked(trimmedArgs[1], trimmedArgs[2], true);
} else if ("-u".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
setFileLocked(trimmedArgs[1], trimmedArgs[2], false);
} else if ("-n".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
setDiskName(trimmedArgs[1], trimmedArgs[2]);
} else if ("-cc65".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
System.err.println("Note: -cc65 is deprecated. Please use -as or -dos as appropriate.");
inputStream = stdinOrFile(trimmedArgs[4]);
putDOS(trimmedArgs[1], new Name(trimmedArgs[2]), trimmedArgs[3], inputStream);
} else if ("-dos".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
inputStream = stdinOrFile(trimmedArgs[4]);
putDOS(trimmedArgs[1], new Name(trimmedArgs[2]), trimmedArgs[3], inputStream);
} else if ("-as".equalsIgnoreCase(trimmedArgs[0])) {
String fname = null;
if (trimmedArgs.length > 4) {
fname = trimmedArgs[2];
inputStream = stdinOrFile(trimmedArgs[3]);
} else {
inputStream = stdinOrFile(trimmedArgs[2]);
}
putAppleSingle(trimmedArgs[1], trimmedArgs.length >= 3 ? fname : null, inputStream);
} else if ("-geos".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
inputStream = stdinOrFile(trimmedArgs[2]);
putGEOS(trimmedArgs[1], inputStream);
} else if ("-dos140".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
createDosDisk(trimmedArgs[1], Disk.APPLE_140KB_DISK);
} else if ("-pas140".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
createPasDisk(trimmedArgs[1], trimmedArgs[2], Disk.APPLE_140KB_DISK);
} else if ("-pas800".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
createPasDisk(trimmedArgs[1], trimmedArgs[2], Disk.APPLE_800KB_DISK);
} else if ("-pro140".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
createProDisk(trimmedArgs[1], trimmedArgs[2], Disk.APPLE_140KB_DISK);
} else if ("-pro800".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
createProDisk(trimmedArgs[1], trimmedArgs[2], Disk.APPLE_800KB_DISK);
} else if ("-convert".equalsIgnoreCase(trimmedArgs[0])) { //$NON-NLS-1$
if (trimmedArgs.length > 3)
convert(trimmedArgs[1], trimmedArgs[2], Integer.parseInt(trimmedArgs[3]));
else
convert(trimmedArgs[1], trimmedArgs[2]);
} else if ("-bas".equalsIgnoreCase(trimmedArgs[0])) {
inputStream = stdinOrFile(trimmedArgs[3]);
putAppleSoft(trimmedArgs[1], trimmedArgs[2], inputStream);
} else {
help();
}
// close out InputStream if we used one
if (inputStream instanceof FileInputStream) {
inputStream.close();
}
argPtr = findNextOperationArg(args, argPtr + 1);
} // while
} catch (Exception ex) {
System.err.println(textBundle.format("CommandLineErrorMessage", //$NON-NLS-1$
ex.getLocalizedMessage()));
@ -201,11 +289,11 @@ public class ac {
* Note that we try to infer the BASIC type dynamically and hard-code the start address
* to 0x801.
*/
public static void putAppleSoft(String imageName, String fileName) throws IOException, DiskException {
File fakeTempSource = File.createTempFile("ac-", "bas");
fakeTempSource.deleteOnExit();
public static void putAppleSoft(String imageName, String fileName, InputStream inputStream) throws IOException, DiskException {
File fakeTempSource = File.createTempFile("ac-", "bas");
fakeTempSource.deleteOnExit();
Configuration config = Configuration.builder().sourceFile(fakeTempSource).build();
Queue<Token> tokens = TokenReader.tokenize(System.in);
Queue<Token> tokens = TokenReader.tokenize(inputStream);
Parser parser = new Parser(tokens);
Program program = parser.parse();
byte[] data = Visitors.byteVisitor(config).dump(program);
@ -271,32 +359,22 @@ public class ac {
}
/**
* Put &lt;stdin&gt. into the file named fileName on the disk named imageName;
* Note: only volume level supported; input size unlimited.
* Put &lt;stdin&gt. as an Apple text file into the file named
* fileName on the disk named imageName.
*/
static void putFile(String imageName, Name name, String fileType,
String address) throws IOException, DiskException {
putFile(imageName, name, fileType, address, System.in);
static void putTxtFileSetHighBit(String imageName, Name name, InputStream inputStream) throws IOException, DiskException {
// Order on the stream is important to ensure the translated newlines have the high bit done appropriately
putFile(imageName, name, "TXT", "0", TranslatorStream.builder(inputStream).lfToCr().setHighBit().get());
}
/**
* Put &lt;stdin&gt. as an Apple text file into the file named
* fileName on the disk named imageName.
*/
static void putTxtFileSetHighBit(String imageName, Name name) throws IOException, DiskException {
// Order on the stream is important to ensure the translated newlines have the high bit done appropriately
putFile(imageName, name, "TXT", "0", TranslatorStream.builder(System.in).lfToCr().setHighBit().get());
}
/**
* Put &lt;stdin&gt. as an Apple text file into the file named
* fileName on the disk named imageName.
*/
static void putTxtFileClearHighBit(String imageName, Name name) throws IOException, DiskException {
// Order on the stream is important to ensure the translated newlines have the high bit done appropriately
putFile(imageName, name, "TXT", "0", TranslatorStream.builder(System.in).lfToCr().clearHighBit().get());
}
/**
* Put &lt;stdin&gt. as an Apple text file into the file named
* fileName on the disk named imageName.
*/
static void putTxtFileClearHighBit(String imageName, Name name, InputStream inputStream) throws IOException, DiskException {
// Order on the stream is important to ensure the translated newlines have the high bit done appropriately
putFile(imageName, name, "TXT", "0", TranslatorStream.builder(inputStream).lfToCr().clearHighBit().get());
}
/**
* Put InputStream into the file named fileName on the disk named imageName;
@ -335,11 +413,11 @@ public class ac {
* Put file fileName into the file named fileOnImageName on the disk named imageName;
* Assume a cc65 style four-byte header with start address in bytes 0-1.
*/
public static void putDOS(String fileName, String imageName, String fileOnImageName, String fileType)
public static void putDOS(String fileName, String imageName, String fileOnImageName, String fileType, InputStream inputStream)
throws IOException, DiskException {
byte[] header = new byte[4];
if (System.in.read(header, 0, 4) == 4) {
if (inputStream.read(header, 0, 4) == 4) {
int address = AppleUtil.getWordValue(header, 0);
putFile(fileName, imageName, fileOnImageName, fileType, Integer.toString(address));
}
@ -349,22 +427,16 @@ public class ac {
* Put &lt;stdin> into the file named fileName on the disk named imageName;
* Assume an DOS 3.x style four-byte header with start address in bytes 0-1.
*/
static void putDOS(String imageName, Name name, String fileType)
static void putDOS(String imageName, Name name, String fileType, InputStream inputStream)
throws IOException, DiskException {
byte[] header = new byte[4];
if (System.in.read(header, 0, 4) == 4) {
if (inputStream.read(header, 0, 4) == 4) {
int address = AppleUtil.getWordValue(header, 0);
putFile(imageName, name, fileType, Integer.toString(address));
putFile(imageName, name, fileType, Integer.toString(address), inputStream);
}
}
/**
* Put file from AppleSingle format into ProDOS image.
*/
public static void putAppleSingle(String imageName, String fileName) throws IOException, DiskException {
putAppleSingle(imageName, fileName, System.in);
}
/**
* AppleSingle shim to allow for unit testing.
*/
@ -395,9 +467,9 @@ public class ac {
* Interpret &lt;stdin> as a GEOS file and place it on the disk named imageName.
* This would only make sense for a ProDOS-formatted disk.
*/
static void putGEOS(String imageName)
static void putGEOS(String imageName, InputStream inputStream)
throws IOException, DiskException {
putFile(imageName, new Name("GEOS-Should Be ProDOS"), "GEO", "0"); //$NON-NLS-2$ $NON-NLS-3$
putFile(imageName, new Name("GEOS-Should Be ProDOS"), "GEO", "0", inputStream); //$NON-NLS-2$ $NON-NLS-3$
}
/**

View File

@ -19,16 +19,14 @@
*/
package io.github.applecommander.acx.command;
import java.util.List;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import com.webcodepro.applecommander.storage.*;
import com.webcodepro.applecommander.storage.DirectoryEntry;
import com.webcodepro.applecommander.storage.Disk;
import com.webcodepro.applecommander.storage.DiskException;
import com.webcodepro.applecommander.storage.FileEntry;
import com.webcodepro.applecommander.util.Name;
import com.webcodepro.applecommander.util.filestreamer.FileStreamer;
import com.webcodepro.applecommander.util.filestreamer.FileTuple;
import com.webcodepro.applecommander.util.filestreamer.TypeOfFile;
import io.github.applecommander.acx.base.ReadWriteDiskCommandOptions;
import io.github.applecommander.acx.converter.DiskConverter;
import io.github.applecommander.acx.fileutil.FileUtils;
@ -36,6 +34,10 @@ import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.CommandLine.Parameters;
import java.util.List;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@Command(name = "copy", description = "Copy files between disks.",
aliases = { "cp" })
public class CopyFileCommand extends ReadWriteDiskCommandOptions {
@ -63,7 +65,7 @@ public class CopyFileCommand extends ReadWriteDiskCommandOptions {
List<FileTuple> files = FileStreamer.forDisk(sourceDisk)
.ignoreErrors(true)
.includeTypeOfFile(TypeOfFile.BOTH)
.recursive(recursiveFlag)
.recursive(false) // we handle recursion in the FileUtils
.matchGlobs(globs)
.stream()
.collect(Collectors.toList());

View File

@ -19,17 +19,16 @@
*/
package io.github.applecommander.acx.fileutil;
import java.util.Optional;
import java.util.logging.Logger;
import com.webcodepro.applecommander.storage.DirectoryEntry;
import com.webcodepro.applecommander.storage.DiskException;
import com.webcodepro.applecommander.storage.FileEntry;
import com.webcodepro.applecommander.util.readerwriter.FileEntryReader;
import com.webcodepro.applecommander.util.readerwriter.FileEntryWriter;
import io.github.applecommander.acx.command.CopyFileCommand;
import java.util.Optional;
import java.util.logging.Logger;
public class FileUtils {
private static Logger LOG = Logger.getLogger(CopyFileCommand.class.getName());
@ -40,7 +39,7 @@ public class FileUtils {
}
public void copy(DirectoryEntry directory, FileEntry file) throws DiskException {
LOG.fine(() -> String.format("Copying '%s'", file.getFilename()));
LOG.fine(() -> String.format("Copying '%s' into directory '%s'", file.getFilename(), directory.getDirname()));
if (file.isDeleted()) {
// Skip deleted files
}
@ -112,13 +111,15 @@ public class FileUtils {
source.getBinaryAddress().ifPresent(target::setBinaryAddress);
source.getBinaryLength().ifPresent(target::setBinaryLength);
source.getAuxiliaryType().ifPresent(target::setAuxiliaryType);
source.getCreationDate().ifPresent(target::setCreationDate);
source.getLastModificationDate().ifPresent(target::setLastModificationDate);
source.getCreationDate().ifPresent(target::setCreationDate);
if (source.getFileData().isPresent() && source.getResourceData().isPresent()) {
target.setFileData(source.getFileData().get(), source.getResourceData().get());
} else {
source.getFileData().ifPresent(target::setFileData);
}
// Modification date needs to be done last since writing file data/attributes are likely to change it
source.getLastModificationDate().ifPresent(target::setLastModificationDate);
}
}

View File

@ -9,11 +9,11 @@ asVersion=1.2.1
btVersion=0.3.1
swtVersion=3.123.0
piSwtVersion=3.8.2
junitVersion=4.12
antVersion=1.8.2
junitVersion=4.13.1
antVersion=1.9.16
commonsLang3Version=3.7
commonsCsvVersion=1.8
gsonVersion=2.8.6
gsonVersion=2.8.9
picocliVersion=4.6.2
springBoot=2.6.1
acdasmVersion=0.4.0

View File

@ -33,6 +33,11 @@ import java.util.List;
* @author Lisias Toledo
*/
public interface DirectoryEntry {
/**
* Return a name for this directory.
*/
public String getDirname();
/**
* Retrieve the list of files in this directory.
* Note that if this is not a directory, the return

View File

@ -19,14 +19,15 @@
*/
package com.webcodepro.applecommander.storage;
import com.webcodepro.applecommander.storage.physical.ImageOrder;
import com.webcodepro.applecommander.util.TextBundle;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.webcodepro.applecommander.storage.physical.ImageOrder;
import com.webcodepro.applecommander.util.TextBundle;
/**
* Abstract representation of a formatted Apple2 disk (floppy, 800k, hard disk).
@ -139,7 +140,14 @@ public abstract class FormattedDisk extends Disk implements DirectoryEntry {
* but "DISK VOLUME #xxx" (DOS 3.3) or "/MY.DISK" (ProDOS).
*/
public abstract String getDiskName();
/**
* Return a name for this directory.
*/
public String getDirname(){
return getDiskName();
}
/**
* Set the name of the disk to volumeName.
*/
@ -404,4 +412,15 @@ public abstract class FormattedDisk extends Disk implements DirectoryEntry {
* Gives an indication on how this disk's geometry should be handled.
*/
public abstract DiskGeometry getDiskGeometry();
/**
* Provides conversation from a given ProDOS file type since as it is common across
* many archiving tools.
*/
public abstract String fromProdosFiletype(String prodosFiletype);
/**
* Provides conversation to a given ProDOS file type since as it is common across
* many archiving tools.
*/
public abstract String toProdosFiletype(String nativeFiletype);
}

View File

@ -19,22 +19,13 @@
*/
package com.webcodepro.applecommander.storage.os.cpm;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import com.webcodepro.applecommander.storage.DirectoryEntry;
import com.webcodepro.applecommander.storage.DiskFullException;
import com.webcodepro.applecommander.storage.DiskGeometry;
import com.webcodepro.applecommander.storage.FileEntry;
import com.webcodepro.applecommander.storage.FormattedDisk;
import com.webcodepro.applecommander.storage.StorageBundle;
import com.webcodepro.applecommander.storage.*;
import com.webcodepro.applecommander.storage.physical.ImageOrder;
import com.webcodepro.applecommander.util.AppleUtil;
import com.webcodepro.applecommander.util.TextBundle;
import java.util.*;
/**
* Manages a disk that is in the Apple CP/M format.
* <p>
@ -565,4 +556,29 @@ public class CpmFormatDisk extends FormattedDisk {
public DiskGeometry getDiskGeometry() {
return DiskGeometry.TRACK_SECTOR;
}
/**
* Provides conversation from a given ProDOS file type since as it is common across
* many archiving tools.
*/
@Override
public String fromProdosFiletype(String prodosFiletype) {
if ("TXT".equalsIgnoreCase(prodosFiletype)) {
return "TXT";
}
return "BIN";
}
/**
* Provides conversation to a given ProDOS file type since as it is common across
* many archiving tools.
*/
@Override
public String toProdosFiletype(String nativeFiletype) {
for (String textFiletype : CpmFileEntry.TEXT_FILETYPES) {
if (textFiletype.equalsIgnoreCase(nativeFiletype)) {
return "TXT";
}
}
return "BIN";
}
}

View File

@ -19,23 +19,13 @@
*/
package com.webcodepro.applecommander.storage.os.dos33;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
import com.webcodepro.applecommander.storage.DirectoryEntry;
import com.webcodepro.applecommander.storage.DiskException;
import com.webcodepro.applecommander.storage.DiskCorruptException;
import com.webcodepro.applecommander.storage.DiskFullException;
import com.webcodepro.applecommander.storage.DiskGeometry;
import com.webcodepro.applecommander.storage.FileEntry;
import com.webcodepro.applecommander.storage.FormattedDisk;
import com.webcodepro.applecommander.storage.StorageBundle;
import com.webcodepro.applecommander.storage.*;
import com.webcodepro.applecommander.storage.physical.ImageOrder;
import com.webcodepro.applecommander.util.AppleUtil;
import com.webcodepro.applecommander.util.TextBundle;
import java.util.*;
/**
* Manages a disk that is in Apple DOS 3.3 format.
* <p>
@ -70,11 +60,20 @@ public class DosFormatDisk extends FormattedDisk {
/**
* The list of filetypes available.
*/
private static final String[] filetypes = {
"T", "A", "I", "B", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
"S", "R", "a", "b" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
private static final String[] FILE_TYPES = {
"T", "A", "I", "B",
"S", "R", "a", "b"
};
private static final Map<String,String> FILE_TYPE_MAPPING = Map.of(
"T", "TXT",
"I", "INT",
"A", "BAS",
"B", "BIN",
"S", "$F1",
"R", "REL",
"a", "$F2",
"b", "$F3"
);
/**
* Use this inner interface for managing the disk usage data.
* This off-loads format-specific implementation to the implementing class.
@ -739,7 +738,7 @@ public class DosFormatDisk extends FormattedDisk {
* specific to each operating system, a simple String is used.
*/
public String[] getFiletypes() {
return filetypes;
return FILE_TYPES;
}
/**
@ -781,4 +780,26 @@ public class DosFormatDisk extends FormattedDisk {
public DiskGeometry getDiskGeometry() {
return DiskGeometry.TRACK_SECTOR;
}
/**
* Provides conversation from a given ProDOS file type since as it is common across
* many archiving tools.
*/
@Override
public String fromProdosFiletype(String prodosFiletype) {
return FILE_TYPE_MAPPING.entrySet()
.stream()
.filter(e -> e.getValue().equals(prodosFiletype))
.map(Map.Entry::getKey)
.findFirst()
.orElse("B");
}
/**
* Provides conversation to a given ProDOS file type since as it is common across
* many archiving tools.
*/
@Override
public String toProdosFiletype(String nativeFiletype) {
return FILE_TYPE_MAPPING.getOrDefault(nativeFiletype, "BIN");
}
}

View File

@ -19,19 +19,14 @@
*/
package com.webcodepro.applecommander.storage.os.gutenberg;
import java.util.ArrayList;
import java.util.List;
import com.webcodepro.applecommander.storage.DirectoryEntry;
import com.webcodepro.applecommander.storage.DiskFullException;
import com.webcodepro.applecommander.storage.DiskGeometry;
import com.webcodepro.applecommander.storage.FileEntry;
import com.webcodepro.applecommander.storage.FormattedDisk;
import com.webcodepro.applecommander.storage.StorageBundle;
import com.webcodepro.applecommander.storage.*;
import com.webcodepro.applecommander.storage.physical.ImageOrder;
import com.webcodepro.applecommander.util.AppleUtil;
import com.webcodepro.applecommander.util.TextBundle;
import java.util.ArrayList;
import java.util.List;
/**
* Manages a disk that is in Gutenberg Word Processor format.
* <p>
@ -707,4 +702,21 @@ public class GutenbergFormatDisk extends FormattedDisk {
public DiskGeometry getDiskGeometry() {
return DiskGeometry.TRACK_SECTOR;
}
/**
* Provides conversation from a given ProDOS file type since as it is common across
* many archiving tools.
*/
@Override
public String fromProdosFiletype(String prodosFiletype) {
return "T";
}
/**
* Provides conversation to a given ProDOS file type since as it is common across
* many archiving tools.
*/
@Override
public String toProdosFiletype(String nativeFiletype) {
return "TXT";
}
}

View File

@ -19,19 +19,14 @@
*/
package com.webcodepro.applecommander.storage.os.nakedos;
import java.util.ArrayList;
import java.util.List;
import com.webcodepro.applecommander.storage.DirectoryEntry;
import com.webcodepro.applecommander.storage.DiskFullException;
import com.webcodepro.applecommander.storage.DiskGeometry;
import com.webcodepro.applecommander.storage.FileEntry;
import com.webcodepro.applecommander.storage.FormattedDisk;
import com.webcodepro.applecommander.storage.StorageBundle;
import com.webcodepro.applecommander.storage.*;
import com.webcodepro.applecommander.storage.physical.ImageOrder;
import com.webcodepro.applecommander.util.AppleUtil;
import com.webcodepro.applecommander.util.TextBundle;
import java.util.ArrayList;
import java.util.List;
/**
* Manages a disk that is in NakedOS format.
* <p>
@ -545,4 +540,21 @@ public class NakedosFormatDisk extends FormattedDisk {
public DiskGeometry getDiskGeometry() {
return DiskGeometry.TRACK_SECTOR;
}
/**
* Provides conversation from a given ProDOS file type since as it is common across
* many archiving tools.
*/
@Override
public String fromProdosFiletype(String prodosFiletype) {
return "B";
}
/**
* Provides conversation to a given ProDOS file type since as it is common across
* many archiving tools.
*/
@Override
public String toProdosFiletype(String nativeFiletype) {
return "BIN";
}
}

View File

@ -21,21 +21,13 @@
*/
package com.webcodepro.applecommander.storage.os.pascal;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Date;
import java.util.List;
import com.webcodepro.applecommander.storage.DirectoryEntry;
import com.webcodepro.applecommander.storage.DiskFullException;
import com.webcodepro.applecommander.storage.DiskGeometry;
import com.webcodepro.applecommander.storage.FileEntry;
import com.webcodepro.applecommander.storage.FormattedDisk;
import com.webcodepro.applecommander.storage.StorageBundle;
import com.webcodepro.applecommander.storage.*;
import com.webcodepro.applecommander.storage.physical.ImageOrder;
import com.webcodepro.applecommander.util.AppleUtil;
import com.webcodepro.applecommander.util.TextBundle;
import java.util.*;
/**
* Manages a disk that is in the Pascal format.
* <p>
@ -58,15 +50,31 @@ public class PascalFormatDisk extends FormattedDisk {
/**
* The known filetypes for a Pascal disk.
*/
private static final String[] filetypes = {
"xdskfile", //$NON-NLS-1$
private static final String[] FILE_TYPES = {
"xdskfile",
CODEFILE,
TEXTFILE,
"INFO", //$NON-NLS-1$
"INFO",
DATAFILE,
"GRAF", //$NON-NLS-1$
"FOTO", //$NON-NLS-1$
"securedir" }; //$NON-NLS-1$
"GRAF",
"FOTO",
"securedir"
};
private static final Map<String,String> FILE_TYPE_MAP = Map.of(
// Pascal => Prodos
"xdskfile", "BAD",
CODEFILE, "BIN",
TEXTFILE, "TXT",
"INFO", "TXT",
DATAFILE, "BIN",
"GRAF", "BIN",
"FOTO", "BIN",
"securedir", "BIN",
// Prodos => Pascal
"BIN", DATAFILE,
"TXT", TEXTFILE
);
/**
* Use this inner interface for managing the disk usage data.
@ -624,7 +632,7 @@ public class PascalFormatDisk extends FormattedDisk {
* specific to each operating system, a simple String is used.
*/
public String[] getFiletypes() {
return filetypes;
return FILE_TYPES;
}
/**
@ -675,4 +683,21 @@ public class PascalFormatDisk extends FormattedDisk {
public DiskGeometry getDiskGeometry() {
return DiskGeometry.BLOCK;
}
/**
* Provides conversation from a given ProDOS file type since as it is common across
* many archiving tools.
*/
@Override
public String fromProdosFiletype(String prodosFiletype) {
return FILE_TYPE_MAP.getOrDefault(prodosFiletype, DATAFILE);
}
/**
* Provides conversation to a given ProDOS file type since as it is common across
* many archiving tools.
*/
@Override
public String toProdosFiletype(String nativeFiletype) {
return FILE_TYPE_MAP.getOrDefault(nativeFiletype, "BIN");
}
}

View File

@ -19,13 +19,13 @@
*/
package com.webcodepro.applecommander.storage.os.prodos;
import java.util.List;
import com.webcodepro.applecommander.storage.DirectoryEntry;
import com.webcodepro.applecommander.storage.DiskException;
import com.webcodepro.applecommander.storage.DiskFullException;
import com.webcodepro.applecommander.storage.FileEntry;
import java.util.List;
/**
* Implement directory functionality.
* <p>
@ -55,6 +55,13 @@ public class ProdosDirectoryEntry extends ProdosFileEntry implements DirectoryEn
return this.subdirectoryHeader;
}
/**
* Return a name for this directory.
*/
public String getDirname(){
return getFilename();
}
/**
* Retrieve the list of files in this directory.
* Note that if this is not a directory, the return

View File

@ -19,27 +19,15 @@
*/
package com.webcodepro.applecommander.storage.os.prodos;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.HashSet;
import com.webcodepro.applecommander.storage.DirectoryEntry;
import com.webcodepro.applecommander.storage.DiskException;
import com.webcodepro.applecommander.storage.DiskCorruptException;
import com.webcodepro.applecommander.storage.DiskFullException;
import com.webcodepro.applecommander.storage.DiskGeometry;
import com.webcodepro.applecommander.storage.FileEntry;
import com.webcodepro.applecommander.storage.FormattedDisk;
import com.webcodepro.applecommander.storage.StorageBundle;
import com.webcodepro.applecommander.storage.*;
import com.webcodepro.applecommander.storage.physical.ImageOrder;
import com.webcodepro.applecommander.util.AppleUtil;
import com.webcodepro.applecommander.util.TextBundle;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
/**
* Manages a disk that is in the ProDOS format.
* <p>
@ -1469,4 +1457,21 @@ public class ProdosFormatDisk extends FormattedDisk {
public DiskGeometry getDiskGeometry() {
return DiskGeometry.BLOCK;
}
/**
* Provides conversation from a given ProDOS file type since as it is common across
* many archiving tools.
*/
@Override
public String fromProdosFiletype(String prodosFiletype) {
return prodosFiletype;
};
/**
* Provides conversation to a given ProDOS file type since as it is common across
* many archiving tools.
*/
@Override
public String toProdosFiletype(String nativeFiletype) {
return nativeFiletype;
};
}

View File

@ -19,21 +19,17 @@
*/
package com.webcodepro.applecommander.storage.os.rdos;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import com.webcodepro.applecommander.storage.DirectoryEntry;
import com.webcodepro.applecommander.storage.DiskFullException;
import com.webcodepro.applecommander.storage.DiskGeometry;
import com.webcodepro.applecommander.storage.FileEntry;
import com.webcodepro.applecommander.storage.FormattedDisk;
import com.webcodepro.applecommander.storage.StorageBundle;
import com.webcodepro.applecommander.storage.*;
import com.webcodepro.applecommander.storage.physical.ImageOrder;
import com.webcodepro.applecommander.storage.physical.ProdosOrder;
import com.webcodepro.applecommander.util.AppleUtil;
import com.webcodepro.applecommander.util.TextBundle;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import java.util.Map;
/**
* Manages a disk that is in the RDOS format.
* <p>
@ -79,7 +75,12 @@ public class RdosFormatDisk extends FormattedDisk {
/**
* The known filetypes for a RDOS disk.
*/
public static final String[] filetypes = { "B", "A", "T" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
public static final String[] FILE_TYPES = { "B", "A", "T" };
private static final Map<String,String> FILE_TYPE_MAPPING = Map.of(
"T", "TXT",
"A", "BAS",
"B", "BIN"
);
/**
* 13 sectors for RDOS 2.1/3.2, native sectoring (16) for RDOS 3.3
@ -517,7 +518,7 @@ public class RdosFormatDisk extends FormattedDisk {
* specific to each operating system, a simple String is used.
*/
public String[] getFiletypes() {
return filetypes;
return FILE_TYPES;
}
/**
@ -570,4 +571,26 @@ public class RdosFormatDisk extends FormattedDisk {
public DiskGeometry getDiskGeometry() {
return DiskGeometry.TRACK_SECTOR;
}
/**
* Provides conversation from a given ProDOS file type since as it is common across
* many archiving tools.
*/
@Override
public String fromProdosFiletype(String prodosFiletype) {
return FILE_TYPE_MAPPING.entrySet()
.stream()
.filter(e -> e.getValue().equals(prodosFiletype))
.map(Map.Entry::getKey)
.findFirst()
.orElse("B");
}
/**
* Provides conversation to a given ProDOS file type since as it is common across
* many archiving tools.
*/
@Override
public String toProdosFiletype(String nativeFiletype) {
return FILE_TYPE_MAPPING.getOrDefault(nativeFiletype, "BIN");
}
}

View File

@ -19,29 +19,14 @@
*/
package com.webcodepro.applecommander.util.readerwriter;
import java.util.Map;
import java.util.Optional;
import com.webcodepro.applecommander.storage.DiskFullException;
import com.webcodepro.applecommander.storage.os.dos33.DosFileEntry;
import com.webcodepro.applecommander.storage.os.dos33.DosFormatDisk;
import com.webcodepro.applecommander.util.AppleUtil;
import java.util.Optional;
public class DosFileEntryReaderWriter implements FileEntryReader, FileEntryWriter {
private static final Map<String,String> FILE_TYPES;
static {
FILE_TYPES = Map.of(
"T", "TXT",
"I", "INT",
"A", "BAS",
"B", "BIN",
"S", "$F1",
"R", "REL",
"a", "$F2",
"b", "$F3"
);
}
private DosFileEntry fileEntry;
public DosFileEntryReaderWriter(DosFileEntry fileEntry) {
@ -62,17 +47,13 @@ public class DosFileEntryReaderWriter implements FileEntryReader, FileEntryWrite
@Override
public Optional<String> getProdosFiletype() {
return Optional.ofNullable(FILE_TYPES.get(fileEntry.getFiletype()));
String prodosFiletype = fileEntry.getFormattedDisk().toProdosFiletype(fileEntry.getFiletype());
return Optional.ofNullable(prodosFiletype);
}
@Override
public void setProdosFiletype(String filetype) {
String dosFileType = FILE_TYPES.entrySet()
.stream()
.filter(e -> e.getValue().equals(filetype))
.map(Map.Entry::getKey)
.findFirst()
.orElse("B");
fileEntry.setFiletype(dosFileType);
String dosFiletype = fileEntry.getFormattedDisk().fromProdosFiletype(filetype);
fileEntry.setFiletype(dosFiletype);
}
@Override

View File

@ -19,35 +19,16 @@
*/
package com.webcodepro.applecommander.util.readerwriter;
import java.util.Date;
import java.util.Map;
import java.util.Optional;
import com.webcodepro.applecommander.storage.DiskFullException;
import com.webcodepro.applecommander.storage.filters.PascalTextFileFilter;
import com.webcodepro.applecommander.storage.os.pascal.PascalFileEntry;
import java.util.Date;
import java.util.Optional;
public class PascalFileEntryReaderWriter implements FileEntryReader, FileEntryWriter {
private static final PascalTextFileFilter TEXT_FILTER = new PascalTextFileFilter();
private static final Map<String,String> FILE_TYPES;
static {
FILE_TYPES = Map.of(
// Pascal => Prodos
"xdskfile", "BAD", // TODO we should skip bad block files
"CODE", "BIN", // TODO is there an address?
"TEXT", "TXT",
"INFO", "TXT", // TODO We should skip debugger info
"DATA", "BIN",
"GRAF", "BIN", // TODO compressed graphics image
"FOTO", "BIN", // TODO screen image
"securedir", "BIN", // TODO is this even implemented
// Prodos => Pascal
"BIN", "DATA",
"TXT", "TEXT"
);
}
private PascalFileEntry fileEntry;
public PascalFileEntryReaderWriter(PascalFileEntry fileEntry) {
@ -65,11 +46,11 @@ public class PascalFileEntryReaderWriter implements FileEntryReader, FileEntryWr
@Override
public Optional<String> getProdosFiletype() {
return Optional.ofNullable(FILE_TYPES.get(fileEntry.getFiletype()));
return Optional.ofNullable(fileEntry.getFormattedDisk().toProdosFiletype(fileEntry.getFiletype()));
}
@Override
public void setProdosFiletype(String filetype) {
fileEntry.setFiletype(FILE_TYPES.getOrDefault(filetype, "DATA"));
fileEntry.setFiletype(fileEntry.getFormattedDisk().fromProdosFiletype(filetype));
}
@Override

View File

@ -19,21 +19,11 @@
*/
package com.webcodepro.applecommander.util.readerwriter;
import java.util.Map;
import java.util.Optional;
import com.webcodepro.applecommander.storage.os.rdos.RdosFileEntry;
import java.util.Optional;
public class RdosFileEntryReader implements FileEntryReader {
private static final Map<String,String> FILE_TYPES;
static {
FILE_TYPES = Map.of(
"T", "TXT",
"A", "BAS",
"B", "BIN"
);
}
private RdosFileEntry fileEntry;
public RdosFileEntryReader(RdosFileEntry fileEntry) {
@ -52,7 +42,7 @@ public class RdosFileEntryReader implements FileEntryReader {
@Override
public Optional<String> getProdosFiletype() {
return Optional.ofNullable(FILE_TYPES.get(fileEntry.getFiletype()));
return Optional.ofNullable(fileEntry.getFormattedDisk().toProdosFiletype(fileEntry.getFiletype()));
}
@Override

View File

@ -104,6 +104,7 @@ CommandLineNoMatchMessage = {0}: No match.
CommandLineStatus = {0} format; {1} bytes free; {2} bytes used.
CommandLineHelp = \
AppleCommander command line options [{0}]:\n\
NOTE: <infile> can either be a local file or '-' for STDIN.\n\
-i <imagename> [<imagename>] display information about image(s).\n\
-ls <imagename> [<imagename>] list brief directory of image(s).\n\
-l <imagename> [<imagename>] list directory of image(s).\n\
@ -117,16 +118,16 @@ CommandLineHelp = \
-e <imagename> <filename> [<output>] export file from image to stdout\n or to an output file.\n\
-x <imagename> [<directory>] extract all files from image to directory.\n\
-g <imagename> <filename> [<output>] get raw file from image to stdout\n or to an output file.\n\
-p <imagename> <filename> <type> [[$|0x]<addr>] put stdin\n in filename on image, using file type and address [0x2000].\n\
-pt <imagename> <filename> put stdin in filename on image\n defaulting to TXT file type, setting high bit on and replacing\n newline characters with $8D.\n\
-ptx <imagename> <filename> put stdin in filename on image\n defaulting to TXT file type, clearing high bit and replacing\n newline characters with $0D.\n\
-p <imagename> <filename> <type> [[$|0x]<addr>] <infile> put infile\n as filename on image, using file type and address [0x2000].\n\
-pt <imagename> <filename> <infile> put infile as filename on image\n defaulting to TXT file type, setting high bit on and replacing\n newline characters with $8D.\n\
-ptx <imagename> <filename> <infile> put infile as filename on image\n defaulting to TXT file type, clearing high bit and replacing\n newline characters with $0D.\n\
-d <imagename> <filename> delete file from image.\n\
-k <imagename> <filename> lock file on image.\n\
-u <imagename> <filename> unlock file on image.\n\
-n <imagename> <volname> change volume name (ProDOS or Pascal).\n\
-dos <imagename> <filename> <type> put stdin with DOS header\n in filename on image, using file type and address from header.\n\
-as <imagename> [<filename>] put stdin with AppleSingle format\n in filename on image, using file type, address, and (optionally) name\n from the AppleSingle file.\n\
-geos <imagename> interpret stdin as a GEOS conversion file and\n place it on image (ProDOS only).\n\
-dos <imagename> <filename> <type> <infile> put infile with DOS header\n as filename on image, using file type and address from header.\n\
-as <imagename> [<filename>] <infile> put infile with AppleSingle format\n as filename on image, using file type, address, and (optionally) name\n from the AppleSingle file.\n\
-geos <imagename> interpret infile as a GEOS conversion file and\n place it on image (ProDOS only).\n\
-dos140 <imagename> create a 140K DOS 3.3 image.\n\
-pro140 <imagename> <volname>\n create a 140K ProDOS image.\n\
-pro800 <imagename> <volname> create an 800K ProDOS image.\n\

View File

@ -211,7 +211,8 @@ public class ImportSelectFilesWizardPane extends WizardPane {
AppleSingle as = AppleSingle.read(data);
suggestedFilename = Optional.ofNullable(as.getRealName())
.orElse(suggestedFilename);
suggestedFiletype = ProdosFormatDisk.getFiletype(as.getProdosFileInfo().getFileType());
suggestedFiletype = wizard.getDisk().fromProdosFiletype(
ProdosFormatDisk.getFiletype(as.getProdosFileInfo().getFileType()));
suggestedAddress = Optional.ofNullable(as.getProdosFileInfo())
.map(ProdosFileInfo::getAuxType)
.orElse(suggestedAddress);
@ -285,7 +286,7 @@ public class ImportSelectFilesWizardPane extends WizardPane {
label.setText(textBundle.get("FiletypeLabel")); //$NON-NLS-1$
final Combo filetypes = new Combo(dialog, SWT.BORDER | SWT.READ_ONLY);
filetypes.setItems(wizard.getDisk().getFiletypes());
if (spec.hasFiletype()) {
if (spec.hasFiletype() && filetypes.indexOf(spec.getFiletype()) != -1) {
filetypes.select(filetypes.indexOf(spec.getFiletype()));
}