summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/anope.example.conf4
-rw-r--r--modules/database/db_flatfile.cpp34
2 files changed, 25 insertions, 13 deletions
diff --git a/data/anope.example.conf b/data/anope.example.conf
index 8c6a96c50..653de1b61 100644
--- a/data/anope.example.conf
+++ b/data/anope.example.conf
@@ -1090,11 +1090,9 @@ module
* Sets the number of days backups of databases are kept. If you don't give it,
* or if you set it to 0, Anope won't backup the databases.
*
- * NOTE: Anope must run 24 hours a day for this feature to work.
- *
* This directive is optional, but recommended.
*/
- keepbackups = 3
+ keepbackups = 7
/*
* Allows Anope to continue file write operations (i.e. database saving)
diff --git a/modules/database/db_flatfile.cpp b/modules/database/db_flatfile.cpp
index 943c9aed4..4039e8879 100644
--- a/modules/database/db_flatfile.cpp
+++ b/modules/database/db_flatfile.cpp
@@ -15,6 +15,8 @@
#include <sys/wait.h>
#endif
+#include <filesystem>
+
class SaveData final
: public Serialize::Data
{
@@ -94,8 +96,6 @@ class DBFlatFile final
{
/* Day the last backup was on */
int last_day = 0;
- /* Backup file names */
- std::map<Anope::string, std::list<Anope::string> > backups;
bool loaded = false;
int child_pid = -1;
@@ -119,11 +119,12 @@ class DBFlatFile final
dbs.insert("module_" + stype->GetOwner()->name + ".db");
}
-
+ const auto backupdir = Anope::ExpandData("backups");
for (const auto &db : dbs)
{
const auto oldname = Anope::ExpandData(db);
- const auto newname = Anope::ExpandData("backups/" + db + "-" + Anope::ToString(tm->tm_year + 1900) + Anope::printf("-%02i-", tm->tm_mon + 1) + Anope::printf("%02i", tm->tm_mday));
+ const auto basename = Anope::Expand(backupdir, db + "-");
+ const auto newname = Anope::printf("%s%04i-%02i-%02i", basename.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
/* Backup already exists or no database to backup */
if (Anope::IsFile(newname) || !Anope::IsFile(oldname))
@@ -144,13 +145,26 @@ class DBFlatFile final
continue;
}
- backups[db].push_back(newname);
-
- unsigned keepbackups = Config->GetModule(this).Get<unsigned>("keepbackups");
- if (keepbackups > 0 && backups[db].size() > keepbackups)
+ std::error_code ec;
+ std::set<Anope::string> old_backups;
+ const auto keepbackups = Config->GetModule(this).Get<unsigned>("keepbackups", "7");
+ for (const auto &entry : std::filesystem::directory_iterator(backupdir.str(), ec))
{
- unlink(backups[db].front().c_str());
- backups[db].pop_front();
+ Anope::string entryname = entry.path().string();
+ if (entryname.compare(0, basename.length(), basename) != 0)
+ continue;
+
+ old_backups.insert(entryname);
+ if (old_backups.size() <= keepbackups)
+ continue;
+
+ Log(LOG_DEBUG) << "Deleting expired backup " << *old_backups.begin();
+ if (!std::filesystem::remove(old_backups.begin()->str(), ec))
+ {
+ Log(this) << "Failed to delete expired backup " << *old_backups.begin() << ": " << ec.message();
+ continue;
+ }
+ old_backups.erase(old_backups.begin());
}
}
}