Skip to content

Instantly share code, notes, and snippets.

@tobozo
Created April 10, 2023 15:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tobozo/79846b167295946a24753a328648fa31 to your computer and use it in GitHub Desktop.
Save tobozo/79846b167295946a24753a328648fa31 to your computer and use it in GitHub Desktop.
ESP32: migrate SPIFFS to LittleFS (experimental)
#include <SPIFFS.h>
#include <LittleFS.h>
#include <vector>
struct CacheFile_t
{
uint8_t* buffer{nullptr};
size_t len{0};
std::string path;
};
std::vector<CacheFile_t> cacheFiles;
void listDir(fs::FS *fs, const char * dirname, uint8_t levels=255){
Serial.printf("Listing directory: %s\r\n", dirname);
File root = fs->open(dirname);
if(!root){
Serial.println("- failed to open directory");
return;
}
if(!root.isDirectory()){
Serial.println(" - not a directory");
return;
}
File file = root.openNextFile();
while(file){
if(file.isDirectory()){
Serial.printf(" DIR : %s\n", file.path() );
if(levels) listDir(fs, file.path(), levels -1);
} else {
Serial.printf(" FILE: %s\t(%d bytes)\n", file.path(), file.size());
}
file = root.openNextFile();
}
root.close();
}
bool cacheFile( fs::File srcFile )
{
if( ! srcFile ) return false;
CacheFile_t cacheFile;
cacheFile.len = srcFile.size();
cacheFile.buffer = (uint8_t*)malloc( cacheFile.len );
cacheFile.path = srcFile.path();
if( cacheFile.buffer == NULL ) return false;
cacheFiles.push_back( cacheFile );
return srcFile.read( cacheFile.buffer, cacheFile.len ) == cacheFile.len;
}
bool cacheRoot( fs::FS *srcFS )
{
fs::File root = srcFS->open("/");
fs::File file = root.openNextFile();
int failed = 0;
while(file){
Serial.printf("Copying FILE: %s\n", file.path());
if( !cacheFile( file ) ) {
log_e("Caching failed for %s", file.path() );
failed++;
}
file = root.openNextFile();
}
root.close();
return failed == 0;
}
bool migrate_SPIFFS_to_LittleFS()
{
Serial.println("SPIFFS -> LittleFS migration tool");
Serial.println("Mounting SPIFFS (may trigger an error)");
if( !SPIFFS.begin() ) {
if(! LittleFS.begin() ) {
Serial.println("Migration unavailable: no SPIFFS/LittleFS partition found, halting");
return false;
}
Serial.println("LittleFS Migration Complete!");
listDir( &LittleFS, "/" );
return true;
}
if( !psramInit() ) {
if( ESP.getFreeHeap() < SPIFFS.usedBytes() + 4096 ) {
Serial.printf("Migration unavailable: not enough heap (needs:%d, has:%d)\n", SPIFFS.usedBytes() + 4096, ESP.getFreeHeap() );
return false;
}
} else if( ESP.getFreePsram() < SPIFFS.usedBytes() + 4096 ) {
Serial.printf("Migration unavailable: not enough psram (needs:%d, has:%d)\n", SPIFFS.usedBytes() + 4096, ESP.getFreePsram() );
return false;
}
Serial.println("SPIFFS migration contents:");
listDir( &SPIFFS, "/" );
Serial.println("Copying items to ram:");
cacheRoot( &SPIFFS );
Serial.println("Unmounting SPIFFS");
SPIFFS.end();
Serial.println("Mounting LittleFS (this will trigger an error but it's okay)");
if( ! LittleFS.begin( true ) ) {
LittleFS.format();
}
Serial.printf("Copying %d items to LittleFS\n", cacheFiles.size() );
for( int i=0; i<cacheFiles.size(); i++ ) {
fs::File outFile = LittleFS.open( cacheFiles[i].path.c_str(), "w", true );
size_t written_bytes = outFile.write( cacheFiles[i].buffer, cacheFiles[i].len );
outFile.close();
Serial.printf("Written %s\t(%d/%d bytes)\n", cacheFiles[i].path.c_str(), written_bytes, cacheFiles[i].len );
}
return true;
}
void setup()
{
Serial.begin( 115200 );
if( migrate_SPIFFS_to_LittleFS() ) {
Serial.println("Migrated items:");
listDir( &LittleFS, "/" );
}
}
void loop()
{
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment