diff --git a/.clang-format b/.clang-format index e9ef8513..51c3af88 100644 --- a/.clang-format +++ b/.clang-format @@ -7,7 +7,7 @@ AllowAllArgumentsOnNextLine: 'true' AllowAllConstructorInitializersOnNextLine: 'false' AllowAllParametersOfDeclarationOnNextLine: 'true' AllowShortBlocksOnASingleLine: 'true' -AllowShortCaseLabelsOnASingleLine: 'true' +AllowShortCaseLabelsOnASingleLine: 'false' AllowShortFunctionsOnASingleLine: Empty AllowShortIfStatementsOnASingleLine: Never AllowShortLambdasOnASingleLine: None diff --git a/arch/brother/decoder.cc b/arch/brother/decoder.cc index 33a3cf31..8a53502a 100644 --- a/arch/brother/decoder.cc +++ b/arch/brother/decoder.cc @@ -1,5 +1,4 @@ #include "globals.h" -#include "sql.h" #include "fluxmap.h" #include "decoders/fluxmapreader.h" #include "decoders/decoders.h" diff --git a/lib/fluxsink/aufluxsink.cc b/lib/fluxsink/aufluxsink.cc index ab41079c..4c4a21a9 100644 --- a/lib/fluxsink/aufluxsink.cc +++ b/lib/fluxsink/aufluxsink.cc @@ -1,7 +1,6 @@ #include "globals.h" #include "flags.h" #include "fluxmap.h" -#include "sql.h" #include "bytes.h" #include "protocol.h" #include "fluxsink/fluxsink.h" diff --git a/lib/fluxsink/fl2fluxsink.cc b/lib/fluxsink/fl2fluxsink.cc index 4516cf88..87b68194 100644 --- a/lib/fluxsink/fl2fluxsink.cc +++ b/lib/fluxsink/fl2fluxsink.cc @@ -1,7 +1,6 @@ #include "globals.h" #include "flags.h" #include "fluxmap.h" -#include "sql.h" #include "bytes.h" #include "protocol.h" #include "fluxsink/fluxsink.h" @@ -18,8 +17,13 @@ class Fl2FluxSink : public FluxSink { public: Fl2FluxSink(const Fl2FluxSinkProto& lconfig): - _config(lconfig), - _of(lconfig.filename(), std::ios::out | std::ios::binary) + Fl2FluxSink(lconfig.filename()) + { + } + + Fl2FluxSink(const std::string& filename): + _filename(filename), + _of(_filename, std::ios::out | std::ios::binary) { if (!_of.is_open()) Error() << "cannot open output file"; @@ -53,11 +57,11 @@ public: operator std::string () const { - return fmt::format("fl2({})", _config.filename()); + return fmt::format("fl2({})", _filename); } private: - const Fl2FluxSinkProto& _config; + std::string _filename; std::ofstream _of; std::map, Bytes> _data; }; @@ -67,4 +71,9 @@ std::unique_ptr FluxSink::createFl2FluxSink(const Fl2FluxSinkProto& co return std::unique_ptr(new Fl2FluxSink(config)); } +std::unique_ptr FluxSink::createFl2FluxSink(const std::string& filename) +{ + return std::unique_ptr(new Fl2FluxSink(filename)); +} + diff --git a/lib/fluxsink/fluxsink.cc b/lib/fluxsink/fluxsink.cc index 1c1f4185..d062a64d 100644 --- a/lib/fluxsink/fluxsink.cc +++ b/lib/fluxsink/fluxsink.cc @@ -11,9 +11,6 @@ std::unique_ptr FluxSink::create(const FluxSinkProto& config) { switch (config.dest_case()) { - case FluxSinkProto::kFluxfile: - return createSqliteFluxSink(config.fluxfile()); - case FluxSinkProto::kDrive: return createHardwareFluxSink(config.drive()); diff --git a/lib/fluxsink/fluxsink.h b/lib/fluxsink/fluxsink.h index a76d11b7..1a137d2f 100644 --- a/lib/fluxsink/fluxsink.h +++ b/lib/fluxsink/fluxsink.h @@ -17,13 +17,14 @@ class FluxSink public: virtual ~FluxSink() {} - static std::unique_ptr createSqliteFluxSink(const std::string& filename); static std::unique_ptr createHardwareFluxSink(const HardwareFluxSinkProto& config); static std::unique_ptr createAuFluxSink(const AuFluxSinkProto& config); static std::unique_ptr createVcdFluxSink(const VcdFluxSinkProto& config); static std::unique_ptr createScpFluxSink(const ScpFluxSinkProto& config); static std::unique_ptr createFl2FluxSink(const Fl2FluxSinkProto& config); + static std::unique_ptr createFl2FluxSink(const std::string& filename); + static std::unique_ptr create(const FluxSinkProto& config); static void updateConfigForFilename(FluxSinkProto* proto, const std::string& filename); diff --git a/lib/fluxsink/fluxsink.proto b/lib/fluxsink/fluxsink.proto index 59ce0ed3..a435be43 100644 --- a/lib/fluxsink/fluxsink.proto +++ b/lib/fluxsink/fluxsink.proto @@ -31,7 +31,6 @@ message Fl2FluxSinkProto { message FluxSinkProto { optional double rescale = 7 [ default = 1.0, (help) = "amount to multiply pulse periods by" ]; oneof dest { - string fluxfile = 1 [(help) = "name of destination flux file"]; HardwareFluxSinkProto drive = 2; AuFluxSinkProto au = 3; VcdFluxSinkProto vcd = 4; diff --git a/lib/fluxsink/scpfluxsink.cc b/lib/fluxsink/scpfluxsink.cc index cf40e234..697dcf0e 100644 --- a/lib/fluxsink/scpfluxsink.cc +++ b/lib/fluxsink/scpfluxsink.cc @@ -1,7 +1,6 @@ #include "globals.h" #include "flags.h" #include "fluxmap.h" -#include "sql.h" #include "bytes.h" #include "protocol.h" #include "fluxsink/fluxsink.h" diff --git a/lib/fluxsink/sqlitefluxsink.cc b/lib/fluxsink/sqlitefluxsink.cc deleted file mode 100644 index a73edf04..00000000 --- a/lib/fluxsink/sqlitefluxsink.cc +++ /dev/null @@ -1,60 +0,0 @@ -#include "globals.h" -#include "fluxmap.h" -#include "sql.h" -#include "fluxsink/fluxsink.h" -#include "flags.h" -#include "fmt/format.h" -#include - -class SqliteFluxSink : public FluxSink -{ -public: - SqliteFluxSink(const std::string& filename): - _filename(filename) - { - if ((access(filename.c_str(), F_OK) == 0) && (remove(filename.c_str()) != 0)) - Error() << fmt::format("failed to overwrite flux file"); - _outdb = sqlOpen(filename, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); - - int oldVersion = sqlReadIntProperty(_outdb, "version"); - if ((oldVersion != 0) && (oldVersion != FLUX_VERSION_CURRENT)) - Error() << fmt::format("that flux file is version {}, but this client is for version {}", - oldVersion, FLUX_VERSION_CURRENT); - - sqlPrepareFlux(_outdb); - sqlStmt(_outdb, "BEGIN;"); - sqlWriteIntProperty(_outdb, "version", FLUX_VERSION_CURRENT); - } - - ~SqliteFluxSink() - { - if (_outdb) - { - sqlStmt(_outdb, "COMMIT;"); - sqlClose(_outdb); - } - } - -public: - void writeFlux(int track, int side, Fluxmap& fluxmap) - { - return sqlWriteFlux(_outdb, track, side, fluxmap); - } - - - operator std::string () const - { - return fmt::format("fluxfile {}", _filename); - } - -private: - sqlite3* _outdb; - std::string _filename; -}; - -std::unique_ptr FluxSink::createSqliteFluxSink(const std::string& filename) -{ - return std::unique_ptr(new SqliteFluxSink(filename)); -} - - diff --git a/lib/fluxsink/vcdfluxsink.cc b/lib/fluxsink/vcdfluxsink.cc index c8260773..ff02b0c3 100644 --- a/lib/fluxsink/vcdfluxsink.cc +++ b/lib/fluxsink/vcdfluxsink.cc @@ -1,7 +1,6 @@ #include "globals.h" #include "flags.h" #include "fluxmap.h" -#include "sql.h" #include "bytes.h" #include "protocol.h" #include "fluxsink/fluxsink.h" diff --git a/lib/fluxsource/fl2fluxsource.cc b/lib/fluxsource/fl2fluxsource.cc index 8ffcfe49..0d101285 100644 --- a/lib/fluxsource/fl2fluxsource.cc +++ b/lib/fluxsource/fl2fluxsource.cc @@ -53,10 +53,8 @@ std::unique_ptr FluxSource::createFl2FluxSource(const Fl2FluxSourceP char buffer[16]; std::ifstream(config.filename(), std::ios::in | std::ios::binary).read(buffer, 16); if (strncmp(buffer, "SQLite format 3", 16) == 0) - { - std::cerr << "Warning: reading a deprecated flux file format; please upgrade it\n"; - return FluxSource::createSqliteFluxSource(config.filename()); - } + Error() << "this flux file is too old; please use the upgrade-flux-file to upgrade it"; + return std::unique_ptr(new Fl2FluxSource(config)); } diff --git a/lib/fluxsource/fluxsource.cc b/lib/fluxsource/fluxsource.cc index 6c2196b4..b92be403 100644 --- a/lib/fluxsource/fluxsource.cc +++ b/lib/fluxsource/fluxsource.cc @@ -18,9 +18,6 @@ std::unique_ptr FluxSource::create(const FluxSourceProto& config) { switch (config.source_case()) { - case FluxSourceProto::kFluxfile: - return createSqliteFluxSource(config.fluxfile()); - case FluxSourceProto::kDrive: return createHardwareFluxSource(config.drive()); diff --git a/lib/fluxsource/fluxsource.h b/lib/fluxsource/fluxsource.h index 9ea0f7b1..b2218b70 100644 --- a/lib/fluxsource/fluxsource.h +++ b/lib/fluxsource/fluxsource.h @@ -26,7 +26,6 @@ private: static std::unique_ptr createHardwareFluxSource(const HardwareFluxSourceProto& config); static std::unique_ptr createKryofluxFluxSource(const KryofluxFluxSourceProto& config); static std::unique_ptr createScpFluxSource(const ScpFluxSourceProto& config); - static std::unique_ptr createSqliteFluxSource(const std::string& filename); static std::unique_ptr createTestPatternFluxSource(const TestPatternFluxSourceProto& config); public: diff --git a/lib/fluxsource/fluxsource.proto b/lib/fluxsource/fluxsource.proto index 8019f31f..53e09726 100644 --- a/lib/fluxsource/fluxsource.proto +++ b/lib/fluxsource/fluxsource.proto @@ -41,7 +41,6 @@ message Fl2FluxSourceProto { message FluxSourceProto { optional double rescale = 9 [ default = 1.0, (help) = "amount to divide pulse periods by" ]; oneof source { - string fluxfile = 1 [default = "name of source flux file"]; HardwareFluxSourceProto drive = 2; TestPatternFluxSourceProto test_pattern = 3; EraseFluxSourceProto erase = 4; diff --git a/lib/fluxsource/sqlitefluxsource.cc b/lib/fluxsource/sqlitefluxsource.cc deleted file mode 100644 index 8e1a5ed5..00000000 --- a/lib/fluxsource/sqlitefluxsource.cc +++ /dev/null @@ -1,42 +0,0 @@ -#include "globals.h" -#include "fluxmap.h" -#include "sql.h" -#include "fluxsource/fluxsource.h" -#include "fmt/format.h" - -class SqliteFluxSource : public FluxSource -{ -public: - SqliteFluxSource(const std::string& filename) - { - _indb = sqlOpen(filename, SQLITE_OPEN_READONLY); - int version = sqlGetVersion(_indb); - if (version != FLUX_VERSION_CURRENT) - Error() << fmt::format("that flux file is version {}, but this client is for version {}", - version, FLUX_VERSION_CURRENT); - } - - ~SqliteFluxSource() - { - if (_indb) - sqlClose(_indb); - } - -public: - std::unique_ptr readFlux(int track, int side) - { - return sqlReadFlux(_indb, track, side); - } - - void recalibrate() {} - -private: - sqlite3* _indb; -}; - -std::unique_ptr FluxSource::createSqliteFluxSource(const std::string& filename) -{ - return std::unique_ptr(new SqliteFluxSource(filename)); -} - - diff --git a/lib/reader.cc b/lib/reader.cc index e3f29bb4..be999b54 100644 --- a/lib/reader.cc +++ b/lib/reader.cc @@ -5,7 +5,6 @@ #include "fluxsink/fluxsink.h" #include "reader.h" #include "fluxmap.h" -#include "sql.h" #include "decoders/decoders.h" #include "sector.h" #include "bytes.h" diff --git a/lib/sql.cc b/lib/sql.cc deleted file mode 100644 index 630a1972..00000000 --- a/lib/sql.cc +++ /dev/null @@ -1,272 +0,0 @@ -#include "globals.h" -#include "sql.h" -#include "fluxmap.h" -#include "bytes.h" -#include "fmt/format.h" - -enum -{ - COMPRESSION_NONE, - COMPRESSION_ZLIB -}; - -static bool hasProperties(sqlite3* db); - -void sqlCheck(sqlite3* db, int i) -{ - if (i != SQLITE_OK) - Error() << "database error: " << sqlite3_errmsg(db); -} - -sqlite3* sqlOpen(const std::string filename, int flags) -{ - sqlite3* db; - int i = sqlite3_open_v2(filename.c_str(), &db, flags, NULL); - if (i != SQLITE_OK) - Error() << "failed: " << sqlite3_errstr(i); - - return db; -} - -void sqlClose(sqlite3* db) -{ - sqlite3_close(db); -} - -void sqlStmt(sqlite3* db, const char* sql) -{ - char* errmsg; - int i = sqlite3_exec(db, sql, NULL, NULL, &errmsg); - if (i != SQLITE_OK) - Error() << "database error: %s" << errmsg; -} - -int sqlGetVersion(sqlite3* db) -{ - return sqlReadIntProperty(db, "version"); -} - -bool hasProperties(sqlite3* db) -{ - sqlite3_stmt* stmt; - sqlCheck(db, sqlite3_prepare_v2(db, - "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='properties'", - -1, &stmt, NULL)); - - int i = sqlite3_step(stmt); - if (i != SQLITE_ROW) - Error() << "Error accessing sqlite metadata"; - bool has_properties = sqlite3_column_int(stmt, 0) != 0; - sqlCheck(db, sqlite3_finalize(stmt)); - - return has_properties; -} - -void sql_bind_blob(sqlite3* db, sqlite3_stmt* stmt, const char* name, - const void* ptr, size_t bytes) -{ - sqlCheck(db, sqlite3_bind_blob(stmt, - sqlite3_bind_parameter_index(stmt, name), - ptr, bytes, SQLITE_TRANSIENT)); -} - -void sql_bind_int(sqlite3* db, sqlite3_stmt* stmt, const char* name, int value) -{ - sqlCheck(db, sqlite3_bind_int(stmt, - sqlite3_bind_parameter_index(stmt, name), - value)); -} - -void sql_bind_string(sqlite3* db, sqlite3_stmt* stmt, const char* name, const char* value) -{ - sqlCheck(db, sqlite3_bind_text(stmt, - sqlite3_bind_parameter_index(stmt, name), - value, -1, SQLITE_TRANSIENT)); -} - -void sqlPrepareFlux(sqlite3* db) -{ - sqlStmt(db, "PRAGMA synchronous = OFF;"); - sqlStmt(db, "PRAGMA auto_vacuum = FULL;"); - sqlStmt(db, "BEGIN;"); - sqlStmt(db, "CREATE TABLE IF NOT EXISTS properties (" - " key TEXT UNIQUE NOT NULL PRIMARY KEY," - " value TEXT" - ");"); - sqlStmt(db, "CREATE TABLE IF NOT EXISTS zdata (" - " track INTEGER," - " side INTEGER," - " data BLOB," - " compression INTEGER," - " PRIMARY KEY(track, side)" - ");"); - sqlStmt(db, "COMMIT;"); -} - -void sqlWriteFlux(sqlite3* db, int track, int side, const Fluxmap& fluxmap) -{ - const auto compressed = fluxmap.rawBytes().compress(); - - sqlite3_stmt* stmt; - sqlCheck(db, sqlite3_prepare_v2(db, - "INSERT OR REPLACE INTO zdata (track, side, data, compression)" - " VALUES (:track, :side, :data, :compression)", - -1, &stmt, NULL)); - sql_bind_int(db, stmt, ":track", track); - sql_bind_int(db, stmt, ":side", side); - sql_bind_blob(db, stmt, ":data", &compressed[0], compressed.size()); - sql_bind_int(db, stmt, ":compression", COMPRESSION_ZLIB); - - if (sqlite3_step(stmt) != SQLITE_DONE) - Error() << "failed to write to database: " << sqlite3_errmsg(db); - sqlCheck(db, sqlite3_finalize(stmt)); -} - -std::unique_ptr sqlReadFlux(sqlite3* db, int track, int side) -{ - sqlite3_stmt* stmt; - sqlCheck(db, sqlite3_prepare_v2(db, - "SELECT data, compression FROM zdata WHERE track=:track AND side=:side", - -1, &stmt, NULL)); - sql_bind_int(db, stmt, ":track", track); - sql_bind_int(db, stmt, ":side", side); - - auto fluxmap = std::unique_ptr(new Fluxmap()); - - int i = sqlite3_step(stmt); - if (i != SQLITE_DONE) - { - if (i != SQLITE_ROW) - Error() << "failed to read from database: " << sqlite3_errmsg(db); - - const uint8_t* blobptr = (const uint8_t*) sqlite3_column_blob(stmt, 0); - size_t bloblen = sqlite3_column_bytes(stmt, 0); - int compression = sqlite3_column_int(stmt, 1); - Bytes data(blobptr, bloblen); - - switch (compression) - { - case COMPRESSION_NONE: - break; - - case COMPRESSION_ZLIB: - data = data.decompress(); - break; - - default: - Error() << fmt::format("unsupported compression type {}", compression); - } - - fluxmap->appendBytes(data); - } - sqlCheck(db, sqlite3_finalize(stmt)); - return fluxmap; -} - -std::vector> sqlFindFlux(sqlite3* db) -{ - std::vector> output; - - sqlite3_stmt* stmt; - sqlCheck(db, sqlite3_prepare_v2(db, - "SELECT track, side FROM zdata", - -1, &stmt, NULL)); - - for (;;) - { - int i = sqlite3_step(stmt); - if (i == SQLITE_DONE) - break; - if (i != SQLITE_ROW) - Error() << "failed to read from database: " << sqlite3_errmsg(db); - - unsigned track = sqlite3_column_int(stmt, 0); - unsigned side = sqlite3_column_int(stmt, 1); - output.push_back(std::make_pair(track, side)); - } - sqlCheck(db, sqlite3_finalize(stmt)); - - return output; -} - -void sqlWriteStringProperty(sqlite3* db, const std::string& name, const std::string& value) -{ - if (!hasProperties(db)) - sqlPrepareFlux(db); - - sqlite3_stmt* stmt; - sqlCheck(db, sqlite3_prepare_v2(db, - "INSERT OR REPLACE INTO properties (key, value) VALUES (:key, :value)", - -1, &stmt, NULL)); - sql_bind_string(db, stmt, ":key", name.c_str()); - sql_bind_string(db, stmt, ":value", value.c_str()); - - if (sqlite3_step(stmt) != SQLITE_DONE) - Error() << "failed to write to database: " << sqlite3_errmsg(db); - sqlCheck(db, sqlite3_finalize(stmt)); -} - -std::string sqlReadStringProperty(sqlite3* db, const std::string& name) -{ - if (!hasProperties(db)) - return ""; - - sqlite3_stmt* stmt; - sqlCheck(db, sqlite3_prepare_v2(db, - "SELECT value FROM properties WHERE key=:key", - -1, &stmt, NULL)); - sql_bind_string(db, stmt, ":key", name.c_str()); - - int i = sqlite3_step(stmt); - std::string result; - if (i != SQLITE_DONE) - { - if (i != SQLITE_ROW) - Error() << "failed to read from database: " << sqlite3_errmsg(db); - - result = (const char*) sqlite3_column_text(stmt, 0); - } - sqlCheck(db, sqlite3_finalize(stmt)); - return result; -} - -void sqlWriteIntProperty(sqlite3* db, const std::string& name, long value) -{ - if (!hasProperties(db)) - sqlPrepareFlux(db); - - sqlite3_stmt* stmt; - sqlCheck(db, sqlite3_prepare_v2(db, - "INSERT OR REPLACE INTO properties (key, value) VALUES (:key, :value)", - -1, &stmt, NULL)); - sql_bind_string(db, stmt, ":key", name.c_str()); - sql_bind_int(db, stmt, ":value", value); - - if (sqlite3_step(stmt) != SQLITE_DONE) - Error() << "failed to write to database: " << sqlite3_errmsg(db); - sqlCheck(db, sqlite3_finalize(stmt)); -} - -long sqlReadIntProperty(sqlite3* db, const std::string& name) -{ - if (!hasProperties(db)) - return 0; - - sqlite3_stmt* stmt; - sqlCheck(db, sqlite3_prepare_v2(db, - "SELECT value FROM properties WHERE key=:key", - -1, &stmt, NULL)); - sql_bind_string(db, stmt, ":key", name.c_str()); - - int i = sqlite3_step(stmt); - long result = 0; - if (i != SQLITE_DONE) - { - if (i != SQLITE_ROW) - Error() << "failed to read from database: " << sqlite3_errmsg(db); - - result = sqlite3_column_int(stmt, 0); - } - sqlCheck(db, sqlite3_finalize(stmt)); - return result; -} \ No newline at end of file diff --git a/lib/sql.h b/lib/sql.h deleted file mode 100644 index 5eab8e39..00000000 --- a/lib/sql.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef SQL_H -#define SQL_H - -#include - -class Fluxmap; - -enum -{ - FLUX_VERSION_0, /* without properties table */ - FLUX_VERSION_1, - FLUX_VERSION_2, /* new bytecode with index marks */ - FLUX_VERSION_3, /* simplified bytecode with six-bit timer */ - - FLUX_VERSION_CURRENT = FLUX_VERSION_3, -}; - -extern void sqlCheck(sqlite3* db, int i); -extern sqlite3* sqlOpen(const std::string filename, int flags); -extern void sqlClose(sqlite3* db); -extern void sqlStmt(sqlite3* db, const char* sql); -extern int sqlGetVersion(sqlite3* db); - -extern void sqlPrepareFlux(sqlite3* db); -extern void sqlWriteFlux(sqlite3* db, int track, int side, const Fluxmap& fluxmap); -extern std::unique_ptr sqlReadFlux(sqlite3* db, int track, int side); -extern std::vector> sqlFindFlux(sqlite3* db); - -extern void sqlWriteStringProperty(sqlite3* db, const std::string& name, const std::string& value); -extern std::string sqlReadStringProperty(sqlite3* db, const std::string& name); - -extern void sqlWriteIntProperty(sqlite3* db, const std::string& name, long value); -extern long sqlReadIntProperty(sqlite3* db, const std::string& name); - -#endif diff --git a/lib/writer.cc b/lib/writer.cc index e80fb531..a1015983 100644 --- a/lib/writer.cc +++ b/lib/writer.cc @@ -2,7 +2,6 @@ #include "flags.h" #include "fluxmap.h" #include "writer.h" -#include "sql.h" #include "protocol.h" #include "usb/usb.h" #include "encoders/encoders.h" @@ -16,8 +15,6 @@ #include "lib/config.pb.h" #include "proto.h" -static sqlite3* outdb; - void writeTracks( FluxSink& fluxSink, const std::function(int track, int side)> producer) diff --git a/mkninja.sh b/mkninja.sh index 1c4b6553..1523354c 100644 --- a/mkninja.sh +++ b/mkninja.sh @@ -438,7 +438,6 @@ buildlibrary libbackend.a \ lib/fluxsink/fluxsink.cc \ lib/fluxsink/hardwarefluxsink.cc \ lib/fluxsink/scpfluxsink.cc \ - lib/fluxsink/sqlitefluxsink.cc \ lib/fluxsink/vcdfluxsink.cc \ lib/fluxsource/cwffluxsource.cc \ lib/fluxsource/erasefluxsource.cc \ @@ -448,7 +447,6 @@ buildlibrary libbackend.a \ lib/fluxsource/kryoflux.cc \ lib/fluxsource/kryofluxfluxsource.cc \ lib/fluxsource/scpfluxsource.cc \ - lib/fluxsource/sqlitefluxsource.cc \ lib/fluxsource/testpatternfluxsource.cc \ lib/globals.cc \ lib/hexdump.cc \ @@ -477,7 +475,6 @@ buildlibrary libbackend.a \ lib/proto.cc \ lib/reader.cc \ lib/sector.cc \ - lib/sql.cc \ lib/usb/fluxengineusb.cc \ lib/usb/greaseweazle.cc \ lib/usb/greaseweazleusb.cc \ @@ -559,7 +556,6 @@ buildlibrary libfrontend.a \ src/fe-seek.cc \ src/fe-testbandwidth.cc \ src/fe-testvoltages.cc \ - src/fe-upgradefluxfile.cc \ src/fe-write.cc \ src/fluxengine.cc \ @@ -590,6 +586,14 @@ buildsimpleprogram brother240tool \ libemu.a \ libfmt.a \ +buildsimpleprogram upgrade-flux-file \ + -Idep/emu \ + tools/upgrade-flux-file.cc \ + libbackend.a \ + libfl2.a \ + libemu.a \ + libfmt.a \ + buildproto libtestproto.a \ -d $OBJDIR/proto/lib/common.pb.h \ tests/testproto.proto \ diff --git a/src/fe-upgradefluxfile.cc b/src/fe-upgradefluxfile.cc deleted file mode 100644 index fb06f4be..00000000 --- a/src/fe-upgradefluxfile.cc +++ /dev/null @@ -1,36 +0,0 @@ -#include "globals.h" -#include "flags.h" -#include "sql.h" -#include "fluxmap.h" -#include "writer.h" -#include "proto.h" -#include "lib/fluxsource/fluxsource.h" -#include "lib/fluxsink/fluxsink.h" -#include "lib/fluxsource/fluxsource.pb.h" -#include "lib/fluxsink/fluxsink.pb.h" -#include "fmt/format.h" -#include - -int mainUpgradeFluxFile(int argc, const char* argv[]) -{ - if (argc != 2) - Error() << "syntax: fluxengine upgradefluxfile "; - std::string filename = argv[1]; - std::string newfilename = filename + ".new"; - - setRange(config.mutable_cylinders(), "0-79"); - setRange(config.mutable_heads(), "0-1"); - - FluxSourceProto fluxSourceProto; - fluxSourceProto.mutable_fl2()->set_filename(filename); - - FluxSinkProto fluxSinkProto; - fluxSinkProto.mutable_fl2()->set_filename(newfilename); - - auto fluxSource = FluxSource::create(fluxSourceProto); - auto fluxSink = FluxSink::create(fluxSinkProto); - writeRawDiskCommand(*fluxSource, *fluxSink); - - rename(newfilename.c_str(), filename.c_str()); - return 0; -} diff --git a/src/fluxengine.cc b/src/fluxengine.cc index c682aed6..c40c8635 100644 --- a/src/fluxengine.cc +++ b/src/fluxengine.cc @@ -14,7 +14,6 @@ extern command_cb mainRpm; extern command_cb mainSeek; extern command_cb mainTestBandwidth; extern command_cb mainTestVoltages; -extern command_cb mainUpgradeFluxFile; extern command_cb mainWrite; struct Command @@ -38,7 +37,6 @@ static std::vector commands = { "rpm", mainRpm, "Measures the disk rotational speed.", }, { "seek", mainSeek, "Moves the disk head.", }, { "test", mainTest, "Various testing commands.", }, - { "upgradefluxfile", mainUpgradeFluxFile, "Upgrades a flux file from a previous version of this software.", }, }; static std::vector analysables = diff --git a/tools/upgrade-flux-file.cc b/tools/upgrade-flux-file.cc new file mode 100644 index 00000000..69f3c796 --- /dev/null +++ b/tools/upgrade-flux-file.cc @@ -0,0 +1,307 @@ +#include "globals.h" +#include "fluxmap.h" +#include "fluxsink/fluxsink.h" +#include "bytes.h" +#include "fmt/format.h" +#include +#include +#include + +/* --- SQL library ------------------------------------------------------- */ + +enum +{ + FLUX_VERSION_0, /* without properties table */ + FLUX_VERSION_1, + FLUX_VERSION_2, /* new bytecode with index marks */ + FLUX_VERSION_3, /* simplified bytecode with six-bit timer */ +}; + +enum +{ + COMPRESSION_NONE, + COMPRESSION_ZLIB +}; + +static bool hasProperties(sqlite3* db); + +void sqlCheck(sqlite3* db, int i) +{ + if (i != SQLITE_OK) + Error() << "database error: " << sqlite3_errmsg(db); +} + +sqlite3* sqlOpen(const std::string filename, int flags) +{ + sqlite3* db; + int i = sqlite3_open_v2(filename.c_str(), &db, flags, NULL); + if (i != SQLITE_OK) + Error() << "failed: " << sqlite3_errstr(i); + + return db; +} + +void sqlClose(sqlite3* db) +{ + sqlite3_close(db); +} + +void sqlStmt(sqlite3* db, const char* sql) +{ + char* errmsg; + int i = sqlite3_exec(db, sql, NULL, NULL, &errmsg); + if (i != SQLITE_OK) + Error() << "database error: %s" << errmsg; +} + +bool hasProperties(sqlite3* db) +{ + sqlite3_stmt* stmt; + sqlCheck(db, + sqlite3_prepare_v2(db, + "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND " + "name='properties'", + -1, + &stmt, + NULL)); + + int i = sqlite3_step(stmt); + if (i != SQLITE_ROW) + Error() << "Error accessing sqlite metadata"; + bool has_properties = sqlite3_column_int(stmt, 0) != 0; + sqlCheck(db, sqlite3_finalize(stmt)); + + return has_properties; +} + +void sql_bind_blob(sqlite3* db, + sqlite3_stmt* stmt, + const char* name, + const void* ptr, + size_t bytes) +{ + sqlCheck(db, + sqlite3_bind_blob(stmt, + sqlite3_bind_parameter_index(stmt, name), + ptr, + bytes, + SQLITE_TRANSIENT)); +} + +void sql_bind_int(sqlite3* db, sqlite3_stmt* stmt, const char* name, int value) +{ + sqlCheck(db, + sqlite3_bind_int( + stmt, sqlite3_bind_parameter_index(stmt, name), value)); +} + +void sql_bind_string( + sqlite3* db, sqlite3_stmt* stmt, const char* name, const char* value) +{ + sqlCheck(db, + sqlite3_bind_text(stmt, + sqlite3_bind_parameter_index(stmt, name), + value, + -1, + SQLITE_TRANSIENT)); +} + +std::vector> sqlFindFlux(sqlite3* db) +{ + std::vector> output; + + sqlite3_stmt* stmt; + sqlCheck(db, + sqlite3_prepare_v2( + db, "SELECT track, side FROM zdata", -1, &stmt, NULL)); + + for (;;) + { + int i = sqlite3_step(stmt); + if (i == SQLITE_DONE) + break; + if (i != SQLITE_ROW) + Error() << "failed to read from database: " << sqlite3_errmsg(db); + + unsigned track = sqlite3_column_int(stmt, 0); + unsigned side = sqlite3_column_int(stmt, 1); + output.push_back(std::make_pair(track, side)); + } + sqlCheck(db, sqlite3_finalize(stmt)); + + return output; +} + +long sqlReadIntProperty(sqlite3* db, const std::string& name) +{ + if (!hasProperties(db)) + return 0; + + sqlite3_stmt* stmt; + sqlCheck(db, + sqlite3_prepare_v2(db, + "SELECT value FROM properties WHERE key=:key", + -1, + &stmt, + NULL)); + sql_bind_string(db, stmt, ":key", name.c_str()); + + int i = sqlite3_step(stmt); + long result = 0; + if (i != SQLITE_DONE) + { + if (i != SQLITE_ROW) + Error() << "failed to read from database: " << sqlite3_errmsg(db); + + result = sqlite3_column_int(stmt, 0); + } + sqlCheck(db, sqlite3_finalize(stmt)); + return result; +} + +int sqlGetVersion(sqlite3* db) +{ + return sqlReadIntProperty(db, "version"); +} + +/* --- Actual program ---------------------------------------------------- */ + +static void syntax() +{ + std::cerr + << "syntax: upgrade-flux-file \n" + << "This tool upgrades the flux file in-place to the current format.\n"; + exit(0); +} + +static Bytes sqlReadFluxBytes(sqlite3* db, int track, int side) +{ + sqlite3_stmt* stmt; + sqlCheck(db, + sqlite3_prepare_v2(db, + "SELECT data, compression FROM zdata WHERE track=:track AND " + "side=:side", + -1, + &stmt, + NULL)); + sql_bind_int(db, stmt, ":track", track); + sql_bind_int(db, stmt, ":side", side); + + Bytes data; + int i = sqlite3_step(stmt); + if (i != SQLITE_DONE) + { + if (i != SQLITE_ROW) + Error() << "failed to read from database: " << sqlite3_errmsg(db); + + const uint8_t* blobptr = (const uint8_t*)sqlite3_column_blob(stmt, 0); + size_t bloblen = sqlite3_column_bytes(stmt, 0); + int compression = sqlite3_column_int(stmt, 1); + data = Bytes(blobptr, bloblen); + + switch (compression) + { + case COMPRESSION_NONE: + break; + + case COMPRESSION_ZLIB: + data = data.decompress(); + break; + + default: + Error() << fmt::format( + "unsupported compression type {}", compression); + } + } + sqlCheck(db, sqlite3_finalize(stmt)); + return data; +} + +static bool isSqlite(const std::string& filename) +{ + char buffer[16]; + std::ifstream(filename, std::ios::in | std::ios::binary).read(buffer, 16); + if (strncmp(buffer, "SQLite format 3", 16) == 0) + return true; + return false; +} + +static void translateFluxVersion2(Fluxmap& fluxmap, const Bytes& bytes) +{ + unsigned pending = 0; + for (uint8_t b : bytes) + { + switch (b) + { + case 0x80: /* pulse */ + fluxmap.appendInterval(pending); + fluxmap.appendPulse(); + pending = 0; + break; + + case 0x81: /* index */ + fluxmap.appendInterval(pending); + fluxmap.appendIndex(); + pending = 0; + break; + + default: + pending += b; + break; + } + } + fluxmap.appendInterval(pending); +} + +int main(int argc, const char* argv[]) +{ + if ((argc != 2) || (strcmp(argv[1], "--help") == 0)) + syntax(); + + std::string filename = argv[1]; + if (!isSqlite(filename)) + { + std::cout << "File is up to date.\n"; + exit(0); + } + + std::string outFilename = filename + ".out.flux"; + auto db = sqlOpen(filename, SQLITE_OPEN_READONLY); + int version = sqlGetVersion(db); + + { + auto fluxsink = FluxSink::createFl2FluxSink(outFilename); + for (const auto& locations : sqlFindFlux(db)) + { + unsigned cylinder = locations.first; + unsigned head = locations.second; + Bytes bytes = sqlReadFluxBytes(db, cylinder, head); + Fluxmap fluxmap; + switch (version) + { + case FLUX_VERSION_2: + translateFluxVersion2(fluxmap, bytes); + break; + + case FLUX_VERSION_3: + fluxmap.appendBytes(bytes); + break; + + default: + Error() << fmt::format( + "you cannot upgrade version {} files (please file a " + "bug)", + version); + } + fluxsink->writeFlux(cylinder, head, fluxmap); + std::cout << '.' << std::flush; + } + + std::cout << "Writing output file...\n"; + } + + if (rename(outFilename.c_str(), filename.c_str()) != 0) + Error() << fmt::format( + "couldn't replace input file: {}", strerror(errno)); + return 0; +}