+// Not in a class due to circular dependancy hell.
+static std::string permchannelsconf;
+static bool WriteDatabase(PermChannel& permchanmode)
+{
+ /*
+ * We need to perform an atomic write so as not to fuck things up.
+ * So, let's write to a temporary file, flush it, then rename the file..
+ * -- w00t
+ */
+
+ // If the user has not specified a configuration file then we don't write one.
+ if (permchannelsconf.empty())
+ return true;
+
+ std::string permchannelsnewconf = permchannelsconf + ".tmp";
+ std::ofstream stream(permchannelsnewconf.c_str());
+ if (!stream.is_open())
+ {
+ ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Cannot create database! %s (%d)", strerror(errno), errno);
+ ServerInstance->SNO->WriteToSnoMask('a', "database: cannot create new db: %s (%d)", strerror(errno), errno);
+ return false;
+ }
+
+ stream << "# This file is automatically generated by m_permchannels. Any changes will be overwritten." << std::endl
+ << "<config format=\"xml\">" << std::endl;
+
+ for (chan_hash::const_iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); i++)
+ {
+ Channel* chan = i->second;
+ if (!chan->IsModeSet(permchanmode))
+ continue;
+
+ stream << "<permchannels channel=\"" << ServerConfig::Escape(chan->name)
+ << "\" topic=\"" << ServerConfig::Escape(chan->topic)
+ << "\" modes=\"" << ServerConfig::Escape(chan->ChanModes(true))
+ << "\">" << std::endl;
+ }
+
+ if (stream.fail())
+ {
+ ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Cannot write to new database! %s (%d)", strerror(errno), errno);
+ ServerInstance->SNO->WriteToSnoMask('a', "database: cannot write to new db: %s (%d)", strerror(errno), errno);
+ return false;
+ }
+ stream.close();
+
+#ifdef _WIN32
+ if (remove(permchannelsconf.c_str()))
+ {
+ ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Cannot remove old database! %s (%d)", strerror(errno), errno);
+ ServerInstance->SNO->WriteToSnoMask('a', "database: cannot remove old database: %s (%d)", strerror(errno), errno);
+ return false;
+ }
+#endif
+ // Use rename to move temporary to new db - this is guarenteed not to fuck up, even in case of a crash.
+ if (rename(permchannelsnewconf.c_str(), permchannelsconf.c_str()) < 0)
+ {
+ ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Cannot move new to old database! %s (%d)", strerror(errno), errno);
+ ServerInstance->SNO->WriteToSnoMask('a', "database: cannot replace old with new db: %s (%d)", strerror(errno), errno);
+ return false;
+ }
+
+ return true;
+}
+