mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-26 18:09:04 +00:00

* Use SafeFile for atomic file writing (with xor checksum readback) * Write db.proto last because it could be the largest file on the FS (and less critical) * Don't keep a tmp file around while writing db.proto (because too big to fit two files in the filesystem) * generate a new critial fault if we encounter errors writing to flash either CriticalErrorCode_FLASH_CORRUPTION_RECOVERABLE or CriticalErrorCode_FLASH_CORRUPTION_UNRECOVERABLE (depending on if the second write attempt worked) * reformat the filesystem if we detect it is corrupted (then rewrite our config files) (only on nrf52 - not sure yet if we should bother on ESP32) * If we have to format the FS, make sure to preserve the oem.proto if it exists Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
49 lines
1.6 KiB
C++
49 lines
1.6 KiB
C++
#pragma once
|
|
|
|
#include "FSCommon.h"
|
|
#include "configuration.h"
|
|
|
|
#ifdef FSCom
|
|
|
|
/**
|
|
* This class provides 'safe'/paranoid file writing.
|
|
*
|
|
* Some of our filesystems (in particular the nrf52) may have bugs beneath our layer. Therefore we want to
|
|
* be very careful about how we write files. This class provides a restricted (Stream only) writing API for writing to files.
|
|
*
|
|
* Notably:
|
|
* - we keep a simple xor hash of all characters that were written.
|
|
* - We do not allow seeking (because we want to maintain our hash)
|
|
* - we provide an close() method which is similar to close but returns false if we were unable to successfully write the
|
|
* file. Also this method
|
|
* - atomically replaces any old version of the file on the disk with our new file (after first rereading the file from the disk
|
|
* to confirm the hash matches)
|
|
* - Some files are super huge so we can't do the full atomic rename/copy (because of filesystem size limits). If !fullAtomic
|
|
* then we still do the readback to verify file is valid so higher level code can handle failures.
|
|
*/
|
|
class SafeFile : public Print
|
|
{
|
|
public:
|
|
SafeFile(char const *filepath, bool fullAtomic = false);
|
|
|
|
virtual size_t write(uint8_t);
|
|
virtual size_t write(const uint8_t *buffer, size_t size);
|
|
|
|
/**
|
|
* Atomically close the file (deleting any old versions) and readback the contents to confirm the hash matches
|
|
*
|
|
* @return false for failure
|
|
*/
|
|
bool close();
|
|
|
|
private:
|
|
/// Read our (closed) tempfile back in and compare the hash
|
|
bool testReadback();
|
|
|
|
String filename;
|
|
File f;
|
|
bool fullAtomic;
|
|
uint8_t hash = 0;
|
|
};
|
|
|
|
#endif |