diff options
Diffstat (limited to 'src/common/lock.cpp')
-rw-r--r-- | src/common/lock.cpp | 46 |
1 files changed, 33 insertions, 13 deletions
diff --git a/src/common/lock.cpp b/src/common/lock.cpp index 2ba9a0a..82856e1 100644 --- a/src/common/lock.cpp +++ b/src/common/lock.cpp @@ -1,36 +1,56 @@ -#include <unistd.h> -#include <stdio.h> #include "lock.hpp" + +#include <unistd.h> + +#include <cstdio> + +#include "cxxstdio.hpp" #include "socket.hpp" +#include "../poison.hpp" + +/// number of backups to keep +static +const int backup_count = 10; + /// Protected file writing /// (Until the file is closed, it keeps the old file) // Start writing a tmpfile -FILE *lock_fopen (const char *filename, int *info) +FILE *lock_fopen(const char *filename, int *info) { - char newfile[512]; FILE *fp; - int no = getpid (); + int no = getpid(); // Get a filename that doesn't already exist + std::string newfile; do { - sprintf (newfile, "%s_%d.tmp", filename, no++); + newfile = STRPRINTF("%s_%d.tmp", filename, no++); + fp = fopen_(newfile.c_str(), "wx"); } - while ((fp = fopen_ (newfile, "r")) && (fclose_ (fp), 1)); + while (!fp); *info = --no; - return fopen_ (newfile, "w"); + return fp; } // Delete the old file and rename the new file -void lock_fclose (FILE * fp, const char *filename, int *info) +void lock_fclose(FILE *fp, const char *filename, int *info) { - char newfile[512]; if (fp) { - fclose_ (fp); - sprintf (newfile, "%s_%d.tmp", filename, *info); - rename (newfile, filename); + fclose_(fp); + int n = backup_count; + std::string old_filename = STRPRINTF("%s.%d", filename, n); + while (--n) + { + std::string newer_filename = STRPRINTF("%s.%d", filename, n); + rename(newer_filename.c_str(), old_filename.c_str()); + old_filename = std::move(newer_filename); + } + rename(filename, old_filename.c_str()); + + std::string tmpfile = STRPRINTF("%s_%d.tmp", filename, *info); + rename(tmpfile.c_str(), filename); } } |