This commit is contained in:
Darafei Praliaskouski 2025-06-05 11:35:16 -07:00 committed by GitHub
commit 227197fff7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 44 additions and 22 deletions

View File

@ -79,23 +79,21 @@ bool copyFile(const char *from, const char *to)
bool renameFile(const char *pathFrom, const char *pathTo)
{
#ifdef FSCom
#ifdef ARCH_ESP32
// take SPI Lock
spiLock->lock();
// rename was fixed for ESP32 IDF LittleFS in April
bool result = FSCom.rename(pathFrom, pathTo);
spiLock->unlock();
return result;
#else
// copyFile does its own locking.
if (copyFile(pathFrom, pathTo) && FSCom.remove(pathFrom)) {
return true;
} else {
return false;
}
bool result = false;
{
concurrency::LockGuard g(spiLock);
#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040) || defined(ARCH_STM32WL)
result = FSCom.rename(pathFrom, pathTo);
#endif
}
if (!result) {
if (copyFile(pathFrom, pathTo)) {
concurrency::LockGuard g(spiLock);
FSCom.remove(pathFrom);
result = true;
}
}
return result;
#endif
}

View File

@ -8,8 +8,10 @@ static File openFile(const char *filename, bool fullAtomic)
concurrency::LockGuard g(spiLock);
LOG_DEBUG("Opening %s, fullAtomic=%d", filename, fullAtomic);
#ifdef ARCH_NRF52
FSCom.remove(filename);
return FSCom.open(filename, FILE_O_WRITE);
if (!fullAtomic) {
FSCom.remove(filename);
return FSCom.open(filename, FILE_O_WRITE);
}
#endif
if (!fullAtomic) {
FSCom.remove(filename); // Nuke the old file to make space (ignore if it !exists)
@ -75,10 +77,9 @@ bool SafeFile::close()
{ // Scope for lock
concurrency::LockGuard g(spiLock);
// brief window of risk here ;-)
if (fullAtomic && FSCom.exists(filename.c_str()) && !FSCom.remove(filename.c_str())) {
LOG_ERROR("Can't remove old pref file");
return false;
if (fullAtomic && FSCom.exists(filename.c_str())) {
// Old config will be replaced by renameFile
// Do not remove here to avoid data loss if power fails before rename
}
}

View File

@ -1049,6 +1049,29 @@ LoadFileResult NodeDB::loadProto(const char *filename, size_t protoSize, size_t
} else {
LOG_ERROR("Could not open / read %s", filename);
}
if (state != LoadFileResult::LOAD_SUCCESS) {
// Try loading from temporary file in case rename was interrupted
String tmp = filename;
tmp += ".tmp";
if (FSCom.exists(tmp.c_str())) {
LOG_WARN("Attempting recovery from %s", tmp.c_str());
auto f2 = FSCom.open(tmp.c_str(), FILE_O_READ);
if (f2) {
pb_istream_t stream = {&readcb, &f2, protoSize};
memset(dest_struct, 0, objSize);
if (pb_decode(&stream, fields, dest_struct)) {
LOG_INFO("Recovered preferences from %s", tmp.c_str());
state = LoadFileResult::LOAD_SUCCESS;
f2.close();
renameFile(tmp.c_str(), filename);
} else {
LOG_ERROR("Recovery decode failed for %s", tmp.c_str());
f2.close();
}
}
}
}
#else
LOG_ERROR("ERROR: Filesystem not implemented");
state = LoadFileResult::NO_FILESYSTEM;