Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,11 @@ public double getDiskRotationalPeriodNs()
diskRotationalPeriodNs = configProto.getDrive().getRotationalPeriodMs() * 1e6;
if (diskRotationalPeriodNs == 0)
{
if (!getFluxSource().isHardware() && !getFluxSinkFactory().isHardware())
throw new FluxEngineException(
"Don't know the rotational speed of the disk; you'll need to set it " +
"manually with --drive.rotational_period_ms=xxx");

usbFactorySupplier.get().perform(device -> {
Logger.log(new BeginOperationLogMessage("Measuring drive rotational speed"));
Logger.log(new BeginSpeedOperationLogMessage());
Expand Down Expand Up @@ -848,7 +853,7 @@ private void writeTracksAndVerify(Disk disk, ImmutableCollection<CylinderHead> l
sector.logicalLocation.head(),
sector.logicalLocation.sector());
}
if (!wanted.empty())
if (!wanted.isEmpty())
{
Logger.logf("missing sector on verify");
return false;
Expand Down
141 changes: 46 additions & 95 deletions java/com/cowlark/fluxengine/config/ConfigBuilder.java
Original file line number Diff line number Diff line change
@@ -1,29 +1,16 @@
package com.cowlark.fluxengine.config;

import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_A2R;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_AU;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_CWF;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_DMK;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_DRIVE;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_ERASE;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_FLUX;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_FLX;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_KRYOFLUX;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_NOP;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_SCP;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_TEST_PATTERN;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_VCD;
import static com.cowlark.fluxengine.config.ImageFormats.Mode.MODE_RO;

import com.cowlark.fluxengine.config.FluxFormats.FluxFormat;
import com.cowlark.fluxengine.config.ImageFormats.ImageFormat;
import com.cowlark.fluxengine.core.FluxEngineException;
import com.cowlark.fluxengine.core.Logger;
import com.cowlark.fluxengine.core.flags.FlagGroup;
import com.cowlark.fluxengine.core.flags.Flags;
import com.cowlark.fluxengine.data.Formats;
import com.cowlark.fluxengine.fluxsink.FluxSinkProto;
import com.cowlark.fluxengine.fluxsource.FluxSource;
import com.cowlark.fluxengine.fluxsource.FluxSourceProto;
import com.cowlark.fluxengine.imagereader.ImageReader;
import com.cowlark.fluxengine.usb.UsbFinder;
import com.google.common.collect.ImmutableList;
Expand All @@ -34,6 +21,7 @@
import java.nio.file.Path;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;

/**
* The assembled configuration, built from the unmatched command-line
Expand Down Expand Up @@ -125,64 +113,41 @@ public ConfigBuilder mergeConfig(ConfigProto other)
return this;
}

private static FluxFormat findFluxFormat(String filename)
{
for (FluxFormat format : FluxFormats.formats)
{
if (format.matcher().matcher(filename).matches())
return format;
}
throw new ConfigException("unrecognised flux filename '" + filename + "'");
}


@SneakyThrows
public ConfigBuilder withFluxSource(String filename)
{
FluxSourceProto.Builder fluxSourceProto = proto.getFluxSourceBuilder();
if (filename.endsWith(".flux"))
{
fluxSourceProto.setType(FLUXTYPE_FLUX);
fluxSourceProto.getFl2Builder().setFilename(filename);
} else if (filename.endsWith(".scp"))
{
fluxSourceProto.setType(FLUXTYPE_SCP);
fluxSourceProto.getScpBuilder().setFilename(filename);
} else if (filename.endsWith(".a2r"))
{
fluxSourceProto.setType(FLUXTYPE_A2R);
fluxSourceProto.getA2RBuilder().setFilename(filename);
} else if (filename.endsWith(".cwf"))
{
fluxSourceProto.setType(FLUXTYPE_CWF);
fluxSourceProto.getCwfBuilder().setFilename(filename);
} else if (filename.startsWith("dmk:"))
{
fluxSourceProto.setType(FLUXTYPE_DMK);
fluxSourceProto.getDmkBuilder().setDirectory(filename.substring(4));
} else if (filename.equals("erase:"))
{
fluxSourceProto.setType(FLUXTYPE_ERASE);
} else if (filename.startsWith("kryoflux:"))
{
fluxSourceProto.setType(FLUXTYPE_KRYOFLUX);
fluxSourceProto.getKryofluxBuilder().setDirectory(filename.substring(9));
} else if (filename.startsWith("testpattern:"))
{
fluxSourceProto.setType(FLUXTYPE_TEST_PATTERN);
} else if (filename.startsWith("drive:"))
{
fluxSourceProto.setType(FLUXTYPE_DRIVE);
proto.getDriveBuilder().setDrive(Integer.parseInt(filename.substring(6)));
} else if (filename.startsWith("flx:"))
{
fluxSourceProto.setType(FLUXTYPE_FLX);
fluxSourceProto.getFlxBuilder().setDirectory(filename.substring(4));
} else if (filename.startsWith("nop:"))
fluxSourceProto.setType(FLUXTYPE_NOP);
else
throw new ConfigException("unrecognised flux filename '" + filename + "'");
FluxFormat format = findFluxFormat(filename);

Matcher matcher = format.matcher().matcher(filename);
matcher.matches();
format.sourceBuilder().accept(matcher.group(1), proto);

/* If the FluxSource has any extra config to contribute, add it here. */

try (FluxSource fluxSource = FluxSource.create(
ConfigProto
.newBuilder()
.setFluxSource(fluxSourceProto)
.setFluxSource(proto.getFluxSource())
.build(), () -> null))
{
ConfigProto extraConfig = fluxSource.getExtraConfig();
if (extraConfig != null)
proto.mergeFrom(extraConfig);
{
/* This merge is backwards so that options set on the command line take precedence
* over what's in the image. */
proto = extraConfig.toBuilder().mergeFrom(proto.build());
}
} catch (FluxEngineException e)
{
/* File not found --- ignore. */
Expand All @@ -192,47 +157,29 @@ public ConfigBuilder withFluxSource(String filename)

public ConfigBuilder withCopyFluxTo(String filename)
{
setFluxSink(proto.getDecoderBuilder().getCopyFluxToBuilder(), filename);
ConfigProto.Builder builder = ConfigProto.newBuilder();

FluxFormat format = findFluxFormat(filename);

Matcher matcher = format.matcher().matcher(filename);
matcher.matches();

format.sinkBuilder().accept(matcher.group(1), builder);
if (builder.getFluxSink().getType() == FLUXTYPE_DRIVE)
throw new ConfigException("you can't copy flux to a hardware device");

proto.getDecoderBuilder().setCopyFluxTo(builder.getFluxSink());
return this;
}

public ConfigBuilder withFluxSink(String filename)
{
setFluxSink(proto.getFluxSinkBuilder(), filename);
return this;
}
FluxFormat format = findFluxFormat(filename);

private void setFluxSink(FluxSinkProto.Builder fluxSink, String filename)
{
if (filename.endsWith(".flux"))
{
fluxSink.setType(FLUXTYPE_FLUX);
fluxSink.getFl2Builder().setFilename(filename);
} else if (filename.endsWith(".scp"))
{
fluxSink.setType(FLUXTYPE_SCP);
fluxSink.getScpBuilder().setFilename(filename);
} else if (filename.endsWith(".a2r"))
{
fluxSink.setType(FLUXTYPE_A2R);
fluxSink.getA2RBuilder().setFilename(filename);
} else if (filename.startsWith("drive:"))
{
fluxSink.setType(FLUXTYPE_DRIVE);
proto.getDriveBuilder().setDrive(Integer.parseInt(filename.substring(6)));
} else if (filename.startsWith("vcd:"))
{
fluxSink.setType(FLUXTYPE_VCD);
fluxSink.getVcdBuilder().setDirectory(filename.substring(4));
} else if (filename.startsWith("au:"))
{
fluxSink.setType(FLUXTYPE_AU);
fluxSink.getAuBuilder().setDirectory(filename.substring(3));
} else if (filename.startsWith("nop:"))
{
fluxSink.setType(FLUXTYPE_NOP);
} else
throw new ConfigException("unrecognised flux filename '" + filename + "'");
Matcher matcher = format.matcher().matcher(filename);
matcher.matches();
format.sinkBuilder().accept(matcher.group(1), proto);
return this;
}

private ImageFormat findImageFormat(String filename)
Expand Down Expand Up @@ -268,7 +215,11 @@ public ConfigBuilder withImageReader(String filename)
{
ConfigProto extraConfig = reader.getExtraConfig();
if (extraConfig != null)
proto.mergeFrom(extraConfig);
{
/* This merge is backwards so that options set on the command line take precedence
* over what's in the image. */
proto = extraConfig.toBuilder().mergeFrom(proto.build());
}
}
return this;
}
Expand Down
173 changes: 173 additions & 0 deletions java/com/cowlark/fluxengine/config/FluxFormats.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
package com.cowlark.fluxengine.config;

import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_A2R;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_AU;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_CWF;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_DMK;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_DRIVE;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_ERASE;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_FLUX;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_FLX;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_KRYOFLUX;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_NOP;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_SCP;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_TEST_PATTERN;
import static com.cowlark.fluxengine.config.FluxSourceSinkType.FLUXTYPE_VCD;

import com.google.common.collect.ImmutableList;
import lombok.Builder;
import java.util.function.BiConsumer;
import java.util.regex.Pattern;

public class FluxFormats
{
private FluxFormats()
{
}

private static BiConsumer<String, ConfigProto.Builder> UNSUPPORTED_SINK = (filename, proto) -> {
throw new ConfigException("this flux format can't be used as a sink");
};

private static BiConsumer<String, ConfigProto.Builder> UNSUPPORTED_SOURCE =
(filename, proto) -> {
throw new ConfigException("this flux format can't be used as a source");
};

public static ImmutableList<FluxFormat> formats = ImmutableList.of(
FluxFormat
.builder()
.setMatcher(Pattern.compile("(.*\\.flux)"))
.setSourceBuilder((filename, proto) -> {
proto.getFluxSourceBuilder().setType(FLUXTYPE_FLUX);
proto.getFluxSourceBuilder().getFl2Builder().setFilename(filename);
})
.setSinkBuilder((filename, proto) -> {
proto.getFluxSinkBuilder().setType(FLUXTYPE_FLUX);
proto.getFluxSinkBuilder().getFl2Builder().setFilename(filename);
})
.build(),
FluxFormat
.builder()
.setMatcher(Pattern.compile("(.*\\.scp)"))
.setSourceBuilder((filename, proto) -> {
proto.getFluxSourceBuilder().setType(FLUXTYPE_SCP);
proto.getFluxSourceBuilder().getScpBuilder().setFilename(filename);
})
.setSinkBuilder((filename, proto) -> {
proto.getFluxSinkBuilder().setType(FLUXTYPE_SCP);
proto.getFluxSinkBuilder().getScpBuilder().setFilename(filename);
})
.build(),
FluxFormat
.builder()
.setMatcher(Pattern.compile("(.*\\.a2r)"))
.setSourceBuilder((filename, proto) -> {
proto.getFluxSourceBuilder().setType(FLUXTYPE_A2R);
proto.getFluxSourceBuilder().getA2RBuilder().setFilename(filename);
})
.setSinkBuilder((filename, proto) -> {
proto.getFluxSinkBuilder().setType(FLUXTYPE_A2R);
proto.getFluxSinkBuilder().getA2RBuilder().setFilename(filename);
})
.build(),
FluxFormat
.builder()
.setMatcher(Pattern.compile("(.*\\.cwf)"))
.setSourceBuilder((filename, proto) -> {
proto.getFluxSourceBuilder().setType(FLUXTYPE_CWF);
proto.getFluxSourceBuilder().getCwfBuilder().setFilename(filename);
})
.setSinkBuilder(UNSUPPORTED_SINK)
.build(),
FluxFormat
.builder()
.setMatcher(Pattern.compile("dmk:(.*)"))
.setSourceBuilder((directory, proto) -> {
proto.getFluxSourceBuilder().setType(FLUXTYPE_DMK);
proto.getFluxSourceBuilder().getDmkBuilder().setDirectory(directory);
})
.setSinkBuilder(UNSUPPORTED_SINK)
.build(),
FluxFormat
.builder()
.setMatcher(Pattern.compile("flx:(.*)"))
.setSourceBuilder((directory, proto) -> {
proto.getFluxSourceBuilder().setType(FLUXTYPE_FLX);
proto.getFluxSourceBuilder().getFlxBuilder().setDirectory(directory);
})
.setSinkBuilder(UNSUPPORTED_SINK)
.build(),
FluxFormat
.builder()
.setMatcher(Pattern.compile("kryoflux:(.*)"))
.setSourceBuilder((directory, proto) -> {
proto.getFluxSourceBuilder().setType(FLUXTYPE_KRYOFLUX);
proto.getFluxSourceBuilder().getKryofluxBuilder().setDirectory(directory);
})
.setSinkBuilder(UNSUPPORTED_SINK)
.build(),
FluxFormat
.builder()
.setMatcher(Pattern.compile("drive:(.*)"))
.setSourceBuilder((filename, proto) -> {
proto.getFluxSourceBuilder().setType(FLUXTYPE_DRIVE);
proto.getDriveBuilder().setDrive(Integer.parseInt(filename));
})
.setSinkBuilder((filename, proto) -> {
proto.getFluxSinkBuilder().setType(FLUXTYPE_DRIVE);
proto.getDriveBuilder().setDrive(Integer.parseInt(filename));
})
.build(),
FluxFormat
.builder()
.setMatcher(Pattern.compile("erase:(.*)"))
.setSourceBuilder(UNSUPPORTED_SOURCE)
.setSinkBuilder((filename, proto) -> {
proto.getFluxSinkBuilder().setType(FLUXTYPE_ERASE);
})
.build(),
FluxFormat
.builder()
.setMatcher(Pattern.compile("testpattern:(.*)"))
.setSourceBuilder(UNSUPPORTED_SOURCE)
.setSinkBuilder((filename, proto) -> {
proto.getFluxSinkBuilder().setType(FLUXTYPE_TEST_PATTERN);
})
.build(),
FluxFormat
.builder()
.setMatcher(Pattern.compile("nop:(.*)"))
.setSourceBuilder((filename, proto) -> {
proto.getFluxSourceBuilder().setType(FLUXTYPE_NOP);
})
.setSinkBuilder((filename, proto) -> {
proto.getFluxSinkBuilder().setType(FLUXTYPE_NOP);
})
.build(),
FluxFormat
.builder()
.setMatcher(Pattern.compile("vcd:(.*)"))
.setSourceBuilder(UNSUPPORTED_SOURCE)
.setSinkBuilder((filename, proto) -> {
proto.getFluxSinkBuilder().setType(FLUXTYPE_VCD);
proto.getFluxSinkBuilder().getVcdBuilder().setDirectory(filename);
})
.build(),
FluxFormat
.builder()
.setMatcher(Pattern.compile("au:(.*)"))
.setSourceBuilder(UNSUPPORTED_SOURCE)
.setSinkBuilder((filename, proto) -> {
proto.getFluxSinkBuilder().setType(FLUXTYPE_AU);
proto.getFluxSinkBuilder().getAuBuilder().setDirectory(filename);
})
.build());

@Builder(setterPrefix = "set")
public record FluxFormat(Pattern matcher, BiConsumer<String, ConfigProto.Builder> sourceBuilder,
BiConsumer<String, ConfigProto.Builder> sinkBuilder)
{
}

}
Loading
Loading