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) bool renameFile(const char *pathFrom, const char *pathTo)
{ {
#ifdef FSCom #ifdef FSCom
bool result = false;
#ifdef ARCH_ESP32 {
// take SPI Lock concurrency::LockGuard g(spiLock);
spiLock->lock(); #if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040) || defined(ARCH_STM32WL)
// rename was fixed for ESP32 IDF LittleFS in April result = FSCom.rename(pathFrom, pathTo);
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;
}
#endif #endif
}
if (!result) {
if (copyFile(pathFrom, pathTo)) {
concurrency::LockGuard g(spiLock);
FSCom.remove(pathFrom);
result = true;
}
}
return result;
#endif #endif
} }

View File

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

View File

@ -1049,6 +1049,29 @@ LoadFileResult NodeDB::loadProto(const char *filename, size_t protoSize, size_t
} else { } else {
LOG_ERROR("Could not open / read %s", filename); 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 #else
LOG_ERROR("ERROR: Filesystem not implemented"); LOG_ERROR("ERROR: Filesystem not implemented");
state = LoadFileResult::NO_FILESYSTEM; state = LoadFileResult::NO_FILESYSTEM;