diff --git a/src/engine/config.cpp b/src/engine/config.cpp index 1a4c9766..137dbdaf 100644 --- a/src/engine/config.cpp +++ b/src/engine/config.cpp @@ -27,6 +27,30 @@ #define CHECK_BUF_SIZE 8192 bool DivConfig::save(const char* path, bool redundancy) { + if (redundancy) { + char oldPath[4096]; + char newPath[4096]; + + if (fileExists(path)==1) { + logD("rotating config files..."); + for (int i=4; i>=0; i--) { + if (i>0) { + snprintf(oldPath,4095,"%s.%d",path,i); + } else { + strncpy(oldPath,path,4095); + } + snprintf(newPath,4095,"%s.%d",path,i+1); + + if (i>=4) { + logV("remove %s",oldPath); + deleteFile(oldPath); + } else { + logV("move %s to %s",oldPath,newPath); + moveFiles(oldPath,newPath); + } + } + } + } logD("opening config for write: %s",path); FILE* f=ps_fopen(path,"wb"); if (f==NULL) { @@ -39,7 +63,9 @@ bool DivConfig::save(const char* path, bool redundancy) { if (fwrite(toWrite.c_str(),1,toWrite.size(),f)!=toWrite.size()) { logW("could not write config file! %s",strerror(errno)); reportError(fmt::sprintf("could not write config file! %s",strerror(errno))); + logV("removing config file"); fclose(f); + deleteFile(path); return false; } } diff --git a/src/fileutils.cpp b/src/fileutils.cpp index a58f92a0..b99b7f13 100644 --- a/src/fileutils.cpp +++ b/src/fileutils.cpp @@ -20,6 +20,10 @@ #include "fileutils.h" #ifdef _WIN32 #include "utfutils.h" +#include +#else +#include +#include #endif FILE* ps_fopen(const char* path, const char* mode) { @@ -29,3 +33,48 @@ FILE* ps_fopen(const char* path, const char* mode) { return fopen(path,mode); #endif } + +// TODO: copy in case of failure +bool moveFiles(const char* src, const char* dest) { +#ifdef _WIN32 + return MoveFileW(utf8To16(src).c_str(),utf8To16(dest).c_str()); +#else + if (rename(src,dest)==-1) { + return false; + } + return true; +#endif +} + +bool deleteFile(const char* path) { +#ifdef _WIN32 + return DeleteFileW(utf8To16(path).c_str()); +#else + return (unlink(path)==0); +#endif +} + +int fileExists(const char* path) { +#ifdef _WIN32 + if (PathFileExistsW(utf8To16(path).c_str()) return 1; + // which errors could PathFileExists possibly throw? + switch (GetLastError()) { + case ERROR_FILE_EXISTS: + return 1; + break; + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + case ERROR_INVALID_DRIVE: + case ERROR_DEV_NOT_EXIST: + case ERROR_NETNAME_DELETED: + case ERROR_BAD_NET_NAME: + return 0; + break; + } + return -1; +#else + if (access(path,F_OK)==0) return 1; + if (errno==ENOENT) return 0; + return -1; +#endif +} diff --git a/src/fileutils.h b/src/fileutils.h index ded2bfb4..093c5765 100644 --- a/src/fileutils.h +++ b/src/fileutils.h @@ -22,5 +22,9 @@ #include FILE* ps_fopen(const char* path, const char* mode); +bool moveFiles(const char* src, const char* dest); +bool deleteFile(const char* path); +// returns 1 if file exists, 0 if it doesn't and -1 on error. +int fileExists(const char* path); #endif