diff --git a/src/build.py b/src/build.py index d45c522a..f8b2f583 100644 --- a/src/build.py +++ b/src/build.py @@ -13,6 +13,7 @@ cxxprogram( "./fe-format.cc", "./fe-fluxfilels.cc", "./fe-fluxfilerm.cc", + "./fe-fluxfilecp.cc", "./fe-getdiskinfo.cc", "./fe-getfile.cc", "./fe-getfileinfo.cc", diff --git a/src/fe-fluxfilecp.cc b/src/fe-fluxfilecp.cc new file mode 100644 index 00000000..0102f918 --- /dev/null +++ b/src/fe-fluxfilecp.cc @@ -0,0 +1,84 @@ +#include "lib/core/globals.h" +#include "lib/config/flags.h" +#include "lib/data/fluxmap.h" +#include "lib/data/sector.h" +#include "lib/config/proto.h" +#include "lib/data/locations.h" +#include "lib/data/flux.h" +#include "lib/external/fl2.h" +#include "lib/external/fl2.pb.h" +#include "src/fluxengine.h" +#include + +static FlagGroup flags; + +static StringFlag inputFilenameFlag({"-i", "--input"}, "input flux file"); +static StringFlag outputFilenameFlag( + {"-o", "--output"}, "output flux file (must exist)"); +static StringFlag tracksFlag({"-t", "--tracks"}, "tracks to copy"); + +static const TrackFluxProto* findTrack( + const FluxFileProto& f, int cylinder, int head) +{ + for (const auto& trackFlux : f.track()) + if ((trackFlux.track() == cylinder) && (trackFlux.head() == head)) + return &trackFlux; + + return nullptr; +} + +static TrackFluxProto* findOrMakeTrack(FluxFileProto& f, int cylinder, int head) +{ + for (auto& trackFlux : *f.mutable_track()) + if ((trackFlux.track() == cylinder) && (trackFlux.head() == head)) + return &trackFlux; + + TrackFluxProto* tf = f.add_track(); + tf->set_track(cylinder); + tf->set_head(head); + return tf; +} + +int mainFluxfileCp(int argc, const char* argv[]) +{ + flags.parseFlags(argc, argv); + if (!inputFilenameFlag.isSet()) + error("you must specify an input filename with -i"); + if (!outputFilenameFlag.isSet()) + error("you must specify an output filename with -o"); + + fmt::print( + "{} -> {}:\n", inputFilenameFlag.get(), outputFilenameFlag.get()); + FluxFileProto inf = loadFl2File(inputFilenameFlag.get()); + FluxFileProto outf = loadFl2File(outputFilenameFlag.get()); + + bool changed = false; + for (const auto& location : parseCylinderHeadsString(tracksFlag)) + { + const TrackFluxProto* intrack = + findTrack(inf, location.cylinder, location.head); + if (!intrack) + { + fmt::print(" location c{}h{} not found\n", + location.cylinder, + location.head); + continue; + } + TrackFluxProto* outtrack = + findOrMakeTrack(outf, location.cylinder, location.head); + fmt::print(" copying c{}h{}\n", location.cylinder, location.head); + for (const auto& flux : intrack->flux()) + outtrack->add_flux(flux); + changed = true; + } + + if (changed) + { + fmt::print("writing back output file\n"); + saveFl2File(outputFilenameFlag.get(), outf); + } + else + fmt::print("output file not modified\n"); + + return 0; +} diff --git a/src/fluxengine.cc b/src/fluxengine.cc index dcfc64d0..4538712d 100644 --- a/src/fluxengine.cc +++ b/src/fluxengine.cc @@ -9,6 +9,7 @@ extern command_cb mainAnalyseLayout; extern command_cb mainConvert; extern command_cb mainFluxfileLs; extern command_cb mainFluxfileRm; +extern command_cb mainFluxfileCp; extern command_cb mainFormat; extern command_cb mainGetDiskInfo; extern command_cb mainGetFile; @@ -84,6 +85,7 @@ static std::vector fluxfileables = { { "ls", mainFluxfileLs, "Lists the contents of a flux file.", }, { "rm", mainFluxfileRm, "Removes flux from a flux file.", }, + { "cp", mainFluxfileCp, "Copies flux from one flux file to another." }, }; // clang-format on