From: Otto Moerbeek Date: Thu, 12 Oct 2023 09:02:17 +0000 (+0200) Subject: Error handling and bulk update of forwards X-Git-Tag: rec-5.0.0-alpha2~1^2~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d6ee98b05977c270fb7d9d9c8d758e8799b94555;p=thirdparty%2Fpdns.git Error handling and bulk update of forwards --- diff --git a/pdns/recursordist/settings/cxxsupport.cc b/pdns/recursordist/settings/cxxsupport.cc index b6db21383c..37ccfc35d4 100644 --- a/pdns/recursordist/settings/cxxsupport.cc +++ b/pdns/recursordist/settings/cxxsupport.cc @@ -134,13 +134,13 @@ static void mergeYamlSubFile(const std::string& configname, Recursorsettings& se pdns::rust::settings::rec::merge(settings, data); } -static void convertACLFile(const string& includeDir, const string& apiDir, const std::string& filename) +static void possiblyConvertACLFile(const string& includeDir, const string& apiDir, const std::string& filename, Logr::log_t log) { auto path = includeDir; path.append("/").append(filename).append(".conf"); auto file = ifstream(path); if (!file.is_open()) { - cerr << "Cannot open " << path << endl; + // Not an error, file just is not there return; } rust::vec result; @@ -170,31 +170,71 @@ static void convertACLFile(const string& includeDir, const string& apiDir, const } string yamlfilename = apiDir; yamlfilename.append("/").append(filename).append(".yml"); - ofstream ofconf(yamlfilename + ".tmp"); + string tmpfilename = yamlfilename + ".tmp"; + ofstream ofconf(tmpfilename); if (!ofconf) { - throw runtime_error("Could not open config file '" + yamlfilename + "' for writing: " + stringerror()); + int err = errno; + log->error(Logr::Error, err, "Cannot open for file for writing YAML", "to", Logging::Loggable(tmpfilename)); + throw runtime_error("YAML Conversion"); } ofconf << "# Generated by pdns-recursor REST API, DO NOT EDIT" << endl; ofconf << yaml << endl; ofconf.close(); - cerr << "Converted " << path << " to " << yamlfilename <error(Logr::Error, err, "Rename failed", "file", Logging::Loggable(path), "to", Logging::Loggable(path + ".converted")); + unlink(tmpfilename.c_str()); + throw runtime_error("YAML Conversion"); + } + + if (rename(tmpfilename.c_str(), yamlfilename.c_str()) != 0) { + int err = errno; + log->error(Logr::Error, err, "Rename failed", "file", Logging::Loggable(tmpfilename), "to", Logging::Loggable(yamlfilename)); + rename((path + ".converted").c_str(), path.c_str()); + throw runtime_error("YAML Conversion"); } - // ERROR CHECKS AND LOG - rename((yamlfilename + ".tmp").c_str(), yamlfilename.c_str()); + log->info(Logr::Notice, "Converted to YAML", "file", Logging::Loggable(path), "to", Logging::Loggable(yamlfilename)); } -static void convertForwardsandAuths(const std::string& includeDir, const std::string& apiDir, Logr::log_t log) +static void fileCopy(const string& src, const string& dst, Logr::log_t log) { - std::vector forwardFiles; - ::arg().gatherIncludes(includeDir, "..conf", forwardFiles); + ifstream ifconf(src); + if (!ifconf) { + log->info(Logr::Error, "Cannot open for file for reading", "file", Logging::Loggable(src)); + throw runtime_error("YAML Conversion"); + } + ofstream ofconf(dst); + if (!ofconf) { + log->info(Logr::Error, "Cannot open for file for writing YAML", "to", Logging::Loggable(dst)); + throw runtime_error("YAML Conversion"); + } + for (;;) { + auto character = ifconf.get(); + if (ifconf.eof()) { + break; + } + if (ifconf.bad()) { + int err = errno; + log->error(Logr::Error, err, "Error reading", "to", Logging::Loggable(src)); + throw runtime_error("YAML Conversion"); + } + ofconf.put(character); + if (ofconf.bad()) { + int err = errno; + log->error(Logr::Error, err, "Error writing YAML", "to", Logging::Loggable(dst)); + throw runtime_error("YAML Conversion"); + } + } + ofconf.close(); + ifconf.close(); +} +static void possiblyConvertForwardsandAuths(const std::string& includeDir, const std::string& apiDir, Logr::log_t log) +{ + std::vector forwAndAuthFiles; + ::arg().gatherIncludes(includeDir, "..conf", forwAndAuthFiles); pdns::rust::settings::rec::Recursorsettings settings; - for (const auto& file : forwardFiles) { + for (const auto& file : forwAndAuthFiles) { auto yaml = pdns::settings::rec::oldStyleSettingsFileToYaml(file, false); - cerr << "Converted YAML for " << file << endl; - cerr << yaml << endl; pdns::rust::settings::rec::merge(settings, yaml); } const string yamlAPiZonesFile = apiDir + "/apizones"; @@ -203,20 +243,18 @@ static void convertForwardsandAuths(const std::string& includeDir, const std::st const std::string origName(zone.file); std::string newName(zone.file); newName.replace(0, includeDir.length(), apiDir); - cerr << "Rename " << origName << ' ' << newName << ' '; - auto ret = rename(origName.c_str(), newName.c_str()); - cerr << ret << ' ' << stringerror() << endl; + log->info(Logr::Notice, "Copying auth zone file", "file", Logging::Loggable(origName), "to", Logging::Loggable(newName)); + fileCopy(origName, newName, log); zone.file = ::rust::String(newName); api_add_auth_zone(yamlAPiZonesFile, zone); } - for (const auto& zone : settings.recursor.forward_zones) { - api_add_forward_zone(yamlAPiZonesFile, zone); - } - for (const auto& zone : settings.recursor.forward_zones_recurse) { - api_add_forward_zone(yamlAPiZonesFile, zone); - } - for (const auto& file : forwardFiles) { - rename(file.c_str(), (file + ".converted").c_str()); + api_add_forward_zones(yamlAPiZonesFile, settings.recursor.forward_zones); + api_add_forward_zones(yamlAPiZonesFile, settings.recursor.forward_zones_recurse); + for (const auto& file : forwAndAuthFiles) { + if (rename(file.c_str(), (file + ".converted").c_str()) != 0) { + int err = errno; + log->error(Logr::Error, err, "Rename failed", "file", Logging::Loggable(file), "to", Logging::Loggable(file + ".converted")); + } } } @@ -238,7 +276,7 @@ void pdns::settings::rec::processAPIDir(const string& includeDirOnCommandLine, p "allow-notify-from" }; for (const auto& file : aclFiles) { - convertACLFile(includeDir, apiDir, file); + possiblyConvertACLFile(includeDir, apiDir, file, log); auto path = apiDir; path.append("/").append(file).append(".yml"); try { @@ -247,7 +285,7 @@ void pdns::settings::rec::processAPIDir(const string& includeDirOnCommandLine, p catch (const runtime_error& err) { } } - convertForwardsandAuths(includeDir, apiDir, log); + possiblyConvertForwardsandAuths(includeDir, apiDir, log); } pdns::settings::rec::YamlSettingsStatus pdns::settings::rec::readYamlSettings(const std::string& configname, const std::string& includeDirOnCommandLine, Recursorsettings& settings, std::string& msg, Logr::log_t log) diff --git a/pdns/recursordist/settings/rust-bridge-in.rs b/pdns/recursordist/settings/rust-bridge-in.rs index 1ee664c173..40e53b144f 100644 --- a/pdns/recursordist/settings/rust-bridge-in.rs +++ b/pdns/recursordist/settings/rust-bridge-in.rs @@ -105,5 +105,6 @@ extern "Rust" { fn api_read_zones(path: &str) -> Result>; fn api_add_auth_zone(file: &str, authzone: AuthZone) -> Result<()>; fn api_add_forward_zone(file: &str, forwardzone: ForwardZone) -> Result<()>; + fn api_add_forward_zones(file: &str, forwardzones: &mut Vec) -> Result<()>; fn api_delete_zone(file: &str, zone: &str) -> Result<()>; } diff --git a/pdns/recursordist/settings/rust/src/bridge.rs b/pdns/recursordist/settings/rust/src/bridge.rs index 370a881074..181e234242 100644 --- a/pdns/recursordist/settings/rust/src/bridge.rs +++ b/pdns/recursordist/settings/rust/src/bridge.rs @@ -465,6 +465,15 @@ pub fn api_add_forward_zone(path: &str, forwardzone: ForwardZone) -> Result<(), zones.forward_zones.push(forwardzone); api_write_zones(path, &zones) } + +// This function is called from C++, it needs to acquire the lock +pub fn api_add_forward_zones(path: &str, forwardzones: &mut Vec) -> Result<(), std::io::Error> { + let _lock = LOCK.lock().unwrap(); + let mut zones = api_read_zones_locked(path, true)?; + zones.forward_zones.append(forwardzones); + api_write_zones(path, &zones) +} + // This function is called from C++, it needs to acquire the lock pub fn api_delete_zone(path: &str, zone: &str) -> Result<(), std::io::Error> { let _lock = LOCK.lock().unwrap();