From eb0d9d439e18d4c0699ee74cc289d14c0a59e099 Mon Sep 17 00:00:00 2001 From: psychon Date: Mon, 30 Mar 2009 18:28:09 +0000 Subject: [PATCH] Some changes to the code rewriting znc.conf Added some error checking and fixes a bug where the exclusive lock we use on the config file was removed. This was because we made the kernel allocate a new inode for the config while our lock was still on the old version of the config file. This should now be fixed. git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@1457 726aef4b-f618-498e-8847-2d620e286838 --- znc.cpp | 52 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/znc.cpp b/znc.cpp index f5f2255a..aafe78be 100644 --- a/znc.cpp +++ b/znc.cpp @@ -482,10 +482,24 @@ CString CZNC::ExpandConfigPath(const CString& sConfigFile) { } bool CZNC::WriteConfig() { - // We first write to a temporary file and then move it to the right place - CFile File(GetConfigFile() + "~"); + if (GetConfigFile().empty()) { + return false; + } - if (GetConfigFile().empty() || !File.Open(O_WRONLY | O_CREAT | O_TRUNC, 0600)) { + // Close the old handle to the config file, we are replacing that file. + m_LockFile.Close(); + + // We first write to a temporary file and then move it to the right place + m_LockFile.SetFileName(GetConfigFile() + "~"); + + if (!m_LockFile.Open(O_WRONLY | O_CREAT | O_TRUNC, 0600)) { + return false; + } + + // We have to "transfer" our lock on the config to the new file. + // The old file (= inode) is going away and thus a lock on it would be + // useless. These lock should always succeed (races, anyone?). + if (!m_LockFile.TryExLock()) { return false; } @@ -499,31 +513,31 @@ bool CZNC::WriteConfig() { CString s6 = (pListener->IsIPV6()) ? "6" : " "; - File.Write("Listen" + s6 + " = " + sHostPortion + CString((pListener->IsSSL()) ? "+" : "") + CString(pListener->GetPort()) + "\n"); + m_LockFile.Write("Listen" + s6 + " = " + sHostPortion + CString((pListener->IsSSL()) ? "+" : "") + CString(pListener->GetPort()) + "\n"); } - File.Write("ConnectDelay = " + CString(m_uiConnectDelay) + "\n"); + m_LockFile.Write("ConnectDelay = " + CString(m_uiConnectDelay) + "\n"); if (!m_sISpoofFile.empty()) { - File.Write("ISpoofFile = " + m_sISpoofFile.FirstLine() + "\n"); + m_LockFile.Write("ISpoofFile = " + m_sISpoofFile.FirstLine() + "\n"); if (!m_sISpoofFormat.empty()) { - File.Write("ISpoofFormat = " + m_sISpoofFormat.FirstLine() + "\n"); + m_LockFile.Write("ISpoofFormat = " + m_sISpoofFormat.FirstLine() + "\n"); } } if (!m_sPidFile.empty()) { - File.Write("PidFile = " + m_sPidFile.FirstLine() + "\n"); + m_LockFile.Write("PidFile = " + m_sPidFile.FirstLine() + "\n"); } if (!m_sStatusPrefix.empty()) { - File.Write("StatusPrefix = " + m_sStatusPrefix.FirstLine() + "\n"); + m_LockFile.Write("StatusPrefix = " + m_sStatusPrefix.FirstLine() + "\n"); } for (unsigned int m = 0; m < m_vsMotd.size(); m++) { - File.Write("Motd = " + m_vsMotd[m].FirstLine() + "\n"); + m_LockFile.Write("Motd = " + m_vsMotd[m].FirstLine() + "\n"); } for (unsigned int v = 0; v < m_vsVHosts.size(); v++) { - File.Write("VHost = " + m_vsVHosts[v].FirstLine() + "\n"); + m_LockFile.Write("VHost = " + m_vsVHosts[v].FirstLine() + "\n"); } #ifdef _MODULES @@ -537,7 +551,7 @@ bool CZNC::WriteConfig() { sArgs = " " + sArgs.FirstLine(); } - File.Write("LoadModule = " + sName.FirstLine() + sArgs + "\n"); + m_LockFile.Write("LoadModule = " + sName.FirstLine() + sArgs + "\n"); } #endif @@ -549,18 +563,22 @@ bool CZNC::WriteConfig() { continue; } - File.Write("\n"); + m_LockFile.Write("\n"); - if (!it->second->WriteConfig(File)) { + if (!it->second->WriteConfig(m_LockFile)) { DEBUG("** Error writing config for user [" << it->first << "]"); } } - File.Sync(); - File.Close(); + // If Sync() fails... well, let's hope nothing important breaks.. + m_LockFile.Sync(); // We wrote to a temporary name, move it to the right place - File.Move(GetConfigFile(), true); + if (!m_LockFile.Move(GetConfigFile(), true)) + return false; + + // Everything went fine, just need to update the saved path. + m_LockFile.SetFileName(GetConfigFile()); return true; }