diff --git a/src/wallet/salvage.h b/src/wallet/salvage.h --- a/src/wallet/salvage.h +++ b/src/wallet/salvage.h @@ -9,6 +9,9 @@ #include #include -bool RecoverDatabaseFile(const fs::path &file_path); +struct bilingual_str; + +bool RecoverDatabaseFile(const fs::path &file_path, bilingual_str &error, + std::vector &warnings); #endif // BITCOIN_WALLET_SALVAGE_H diff --git a/src/wallet/salvage.cpp b/src/wallet/salvage.cpp --- a/src/wallet/salvage.cpp +++ b/src/wallet/salvage.cpp @@ -17,14 +17,13 @@ static const char *DATA_END = "DATA=END"; typedef std::pair, std::vector> KeyValPair; -bool RecoverDatabaseFile(const fs::path &file_path) { +bool RecoverDatabaseFile(const fs::path &file_path, bilingual_str &error, + std::vector &warnings) { std::string filename; std::shared_ptr env = GetWalletEnv(file_path, filename); - bilingual_str open_err; - if (!env->Open(open_err)) { - tfm::format(std::cerr, "%s\n", open_err.original); + if (!env->Open(error)) { return false; } @@ -40,10 +39,9 @@ int result = env->dbenv->dbrename(nullptr, filename.c_str(), nullptr, newFilename.c_str(), DB_AUTO_COMMIT); - if (result == 0) { - LogPrintf("Renamed %s to %s\n", filename, newFilename); - } else { - LogPrintf("Failed to rename %s to %s\n", filename, newFilename); + if (result != 0) { + error = strprintf(Untranslated("Failed to rename %s to %s"), filename, + newFilename); return false; } @@ -62,11 +60,14 @@ result = db.verify(newFilename.c_str(), nullptr, &strDump, DB_SALVAGE | DB_AGGRESSIVE); if (result == DB_VERIFY_BAD) { - LogPrintf("Salvage: Database salvage found errors, all data may not be " - "recoverable.\n"); + warnings.push_back( + Untranslated("Salvage: Database salvage found errors, all data may " + "not be recoverable.")); } if (result != 0 && result != DB_VERIFY_BAD) { - LogPrintf("Salvage: Database salvage failed with result %d.\n", result); + error = strprintf( + Untranslated("Salvage: Database salvage failed with result %d."), + result); return false; } @@ -92,8 +93,9 @@ } getline(strDump, valueHex); if (valueHex == DATA_END) { - LogPrintf("Salvage: WARNING: Number of keys in data does not " - "match number of values.\n"); + warnings.push_back( + Untranslated("Salvage: WARNING: Number of keys in data " + "does not match number of values.")); break; } salvagedData.push_back( @@ -103,18 +105,19 @@ bool fSuccess; if (keyHex != DATA_END) { - LogPrintf("Salvage: WARNING: Unexpected end of file while reading " - "salvage output.\n"); + warnings.push_back(Untranslated("Salvage: WARNING: Unexpected end of " + "file while reading salvage output.")); fSuccess = false; } else { fSuccess = (result == 0); } if (salvagedData.empty()) { - LogPrintf("Salvage(aggressive) found no records in %s.\n", newFilename); + error = strprintf( + Untranslated("Salvage(aggressive) found no records in %s."), + newFilename); return false; } - LogPrintf("Salvage(aggressive) found %u records\n", salvagedData.size()); std::unique_ptr pdbCopy = std::make_unique(env->dbenv.get(), 0); int ret = pdbCopy->open(nullptr, // Txn pointer @@ -124,7 +127,8 @@ DB_CREATE, // Flags 0); if (ret > 0) { - LogPrintf("Cannot create database file %s\n", filename); + error = + strprintf(Untranslated("Cannot create database file %s"), filename); pdbCopy->close(0); return false; } @@ -148,8 +152,9 @@ continue; } if (!fReadOK) { - LogPrintf("WARNING: WalletBatch::Recover skipping %s: %s\n", - strType, strErr); + warnings.push_back(strprintf( + Untranslated("WARNING: WalletBatch::Recover skipping %s: %s"), + strType, strErr)); continue; } Dbt datKey(&row.first[0], row.first.size()); diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp --- a/src/wallet/wallettool.cpp +++ b/src/wallet/wallettool.cpp @@ -148,7 +148,18 @@ WalletShowInfo(wallet_instance.get()); wallet_instance->Flush(true); } else if (command == "salvage") { - return RecoverDatabaseFile(path); + bilingual_str error; + std::vector warnings; + bool ret = RecoverDatabaseFile(path, error, warnings); + if (!ret) { + for (const auto &warning : warnings) { + tfm::format(std::cerr, "%s\n", warning.original); + } + if (!error.empty()) { + tfm::format(std::cerr, "%s\n", error.original); + } + } + return ret; } } else { tfm::format(std::cerr, "Invalid command: %s\n", command);