From a7a79b3c768a8e7f8aa333aede8b2baeb62a8b1a Mon Sep 17 00:00:00 2001 From: Wiebe Cazemier Date: Wed, 31 Aug 2022 18:47:37 +0200 Subject: [PATCH] Improve error handling on persistence files --- persistencefile.cpp | 43 ++++++++++++++++++++++++++++++++++++++++--- persistencefile.h | 1 + 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/persistencefile.cpp b/persistencefile.cpp index a41965b..25d7bd3 100644 --- a/persistencefile.cpp +++ b/persistencefile.cpp @@ -25,6 +25,7 @@ License along with FlashMQ. If not, see . #include #include #include +#include #include "utils.h" #include "logger.h" @@ -39,11 +40,28 @@ PersistenceFile::PersistenceFile(const std::string &filePath) : this->filePath = filePath; this->filePathTemp = formatString("%s.newfile.%s", filePath.c_str(), getSecureRandomString(8).c_str()); this->filePathCorrupt = formatString("%s.corrupt.%s", filePath.c_str(), getSecureRandomString(8).c_str()); + + std::vector d1(filePath.length() + 1, 0); + std::copy(filePath.begin(), filePath.end(), d1.begin()); + this->dirPath = std::string(dirname(d1.data())); } PersistenceFile::~PersistenceFile() { - closeFile(); + try + { + closeFile(); + } + catch(std::exception &ex) + { + Logger::getInstance()->logf(LOG_WARNING, ex.what()); + } + + if (f != nullptr) + { + fclose(f); // fclose was already attempted and error handled if it was possible. In case an early fault happend, we need to still make sure. + f = nullptr; + } if (digestContext) { @@ -105,7 +123,6 @@ void PersistenceFile::hashFile() fseek(f, MAGIC_STRING_LENGH, SEEK_SET); writeCheck(md_value, output_len, 1, f); - fflush(f); } void PersistenceFile::verifyHash() @@ -325,18 +342,38 @@ void PersistenceFile::closeFile() return; if (openMode == FileMode::write) + { hashFile(); + if (fflush(f) != 0) + { + std::string msg(strerror(errno)); + throw std::runtime_error(formatString("Flush of '%s' failed: %s.", this->filePathTemp.c_str(), msg.c_str())); + } + + fsync(f->_fileno); + } + if (f != nullptr) { - fclose(f); + FILE *f2 = f; f = nullptr; + + if (fclose(f2) < 0) + { + std::string msg(strerror(errno)); + throw std::runtime_error(formatString("Close of '%s' failed: %s.", this->filePathTemp.c_str(), msg.c_str())); + } } if (openMode == FileMode::write && !filePathTemp.empty() && ! filePath.empty()) { if (rename(filePathTemp.c_str(), filePath.c_str()) < 0) throw std::runtime_error(formatString("Saving '%s' failed: rename of temp file to target failed with: %s", filePath.c_str(), strerror(errno))); + + int dir_fd = open(this->dirPath.c_str(), O_RDONLY); + fsync(dir_fd); + close(dir_fd); } } diff --git a/persistencefile.h b/persistencefile.h index 3acc924..121d9e5 100644 --- a/persistencefile.h +++ b/persistencefile.h @@ -46,6 +46,7 @@ class PersistenceFile std::string filePath; std::string filePathTemp; std::string filePathCorrupt; + std::string dirPath; EVP_MD_CTX *digestContext = nullptr; const EVP_MD *sha512 = EVP_sha512(); -- libgit2 0.21.4