ESP3D/esp3d/src/modules/filesystem/esp_globalFS.cpp
Luc 3ffb7c3b4c
Fix FTP not listing on some shared SD (#958)
* Fix Rename not working on GlobalFS

* esp3d_log refactoring
 - Rename Debug to Log
 - Allow now 4 level of log: None, Error, Debug, Verbose
 - Change original verbose log to error log when it is an error

* Update configuration.h to add debug level expected

* Add log for critical steps in FTP module
2023-10-27 12:40:22 +08:00

769 lines
17 KiB
C++

/*
esp_globalFS.cpp - ESP3D global FS support class
Copyright (c) 2014 Luc Lebosse. All rights reserved.
This code is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with This code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// #define ESP_LOG_FEATURE LOG_OUTPUT_SERIAL0
#include "../../include/esp3d_config.h"
#if defined(GLOBAL_FILESYSTEM_FEATURE)
#include "esp_globalFS.h"
// to verify FS is accessible
bool ESP_GBFS::isavailable(uint8_t FS) {
#ifdef FILESYSTEM_FEATURE
if (FS == FS_FLASH) {
return ESP_FileSystem::started();
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (FS == FS_SD) {
return (ESP_SD::getState(true) == ESP_SDCARD_IDLE);
}
#endif // SD_DEVICE
return false;
}
uint8_t ESP_GBFS::_nbFS = 0;
String ESP_GBFS::_rootlist[MAX_FS];
// helper to format size to readable string
String &ESP_GBFS::formatBytes(uint64_t bytes) {
static String res;
if (bytes < 1024) {
res = String((uint16_t)bytes) + " B";
} else if (bytes < (1024 * 1024)) {
res = String((float)(bytes / 1024.0), 2) + " KB";
} else if (bytes < (1024 * 1024 * 1024)) {
res = String((float)(bytes / 1024.0 / 1024.0), 2) + " MB";
} else {
res = String((float)(bytes / 1024.0 / 1024.0 / 1024.0), 2) + " GB";
}
return res;
}
// depending FS
uint64_t ESP_GBFS::totalBytes(uint8_t FS) {
#ifdef FILESYSTEM_FEATURE
if (FS == FS_FLASH) {
return ESP_FileSystem::totalBytes();
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (FS == FS_SD) {
return ESP_SD::totalBytes();
}
#endif // SD_DEVICE
return 0;
}
uint64_t ESP_GBFS::usedBytes(uint8_t FS) {
#ifdef FILESYSTEM_FEATURE
if (FS == FS_FLASH) {
return ESP_FileSystem::usedBytes();
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (FS == FS_SD) {
return ESP_SD::usedBytes();
}
#endif // SD_DEVICE
return 0;
}
uint ESP_GBFS::maxPathLength() {
uint size = 255;
#ifdef FILESYSTEM_FEATURE
if (size > 32) {
size = 32;
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (size > 255) {
size = 255;
}
#endif // SD_DEVICE
return size;
}
bool ESP_GBFS::accessFS(uint8_t FS) {
if (FS == FS_ROOT) {
return true;
}
#ifdef FILESYSTEM_FEATURE
if (FS == FS_FLASH) {
return ESP_FileSystem::accessFS();
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (FS == FS_SD) {
bool canAccess = ESP_SD::accessFS();
if (canAccess) {
if (ESP_SD::getState(true) == ESP_SDCARD_NOT_PRESENT) {
canAccess = false;
ESP_SD::releaseFS();
} else {
ESP_SD::setState(ESP_SDCARD_BUSY);
canAccess = true;
}
}
return canAccess;
}
#endif // SD_DEVICE
return false;
}
void ESP_GBFS::releaseFS(uint8_t FS) {
#ifdef FILESYSTEM_FEATURE
if (FS == FS_FLASH) {
ESP_FileSystem::releaseFS();
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (FS == FS_SD) {
ESP_SD::releaseFS();
}
#endif // SD_DEVICE
}
uint64_t ESP_GBFS::freeBytes(uint8_t FS) {
#ifdef FILESYSTEM_FEATURE
if (FS == FS_FLASH) {
return ESP_FileSystem::freeBytes();
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (FS == FS_SD) {
return ESP_SD::freeBytes();
}
#endif // SD_DEVICE
return 0;
}
// Format is not always available for all FS
bool format(uint8_t FS, ESP3DOutput *output = nullptr) {
#ifdef FILESYSTEM_FEATURE
if (FS == FS_FLASH) {
return ESP_FileSystem::format();
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (FS == FS_SD) {
return ESP_SD::format(output);
}
#endif // SD_DEVICE
output->printERROR("Not available");
return false;
}
// check type of FS according root dir
uint8_t ESP_GBFS::getFSType(const char *path) {
String p = path;
p.trim();
if (p == "/") {
return FS_ROOT;
}
#if defined(FILESYSTEM_FEATURE)
if (p.startsWith(ESP_FLASH_FS_HEADER)) {
return FS_FLASH;
}
#endif // FILESYSTEM_FEATURE
#if defined(SD_DEVICE)
if (p.startsWith(ESP_SD_FS_HEADER)) {
return FS_SD;
}
#endif // SD_DEVICE
return FS_UNKNOWN;
}
const char *ESP_GBFS::getRealPath(const char *path) {
static String p;
uint8_t t = getFSType(path);
p = "";
#if defined(FILESYSTEM_FEATURE)
if (t == FS_FLASH) {
p = path;
// remove header
p.remove(0, strlen(ESP_FLASH_FS_HEADER));
// if nothing it is root
if (p.length() == 0) {
p = "/";
}
}
#endif // FILESYSTEM_FEATURE
#if defined(SD_DEVICE)
if (t == FS_SD) {
p = path;
// remove header
p.remove(0, strlen(ESP_SD_FS_HEADER));
// if nothing it is root
if (p.length() == 0) {
p = "/";
}
}
#endif // SD_DEVICE
return p.c_str();
}
// path exists on / or SD or FS
bool ESP_GBFS::exists(const char *path) {
#if defined(FILESYSTEM_FEATURE) || defined(SD_DEVICE)
uint8_t t = getFSType(path);
if (t == FS_ROOT) {
return true;
}
#if defined(FILESYSTEM_FEATURE)
if (t == FS_FLASH) {
return ESP_FileSystem::exists(getRealPath(path));
}
#endif // FILESYSTEM_FEATURE
#if defined(SD_DEVICE)
if (t == FS_SD) {
return ESP_SD::exists(getRealPath(path));
}
#endif // SD_DEVICE
#endif // FILESYSTEM_FEATURE || SD_DEVICE
return false;
}
bool ESP_GBFS::remove(const char *path) {
#if defined(FILESYSTEM_FEATURE) || defined(SD_DEVICE)
uint8_t t = getFSType(path);
if (t == FS_ROOT) {
return false;
}
#if defined(FILESYSTEM_FEATURE)
if (t == FS_FLASH) {
return ESP_FileSystem::remove(getRealPath(path));
}
#endif // FILESYSTEM_FEATURE
#if defined(SD_DEVICE)
if (t == FS_SD) {
return ESP_SD::remove(getRealPath(path));
}
#endif // SD_DEVICE
#endif // FILESYSTEM_FEATURE || SD_DEVICE
return false;
}
bool ESP_GBFS::rename(const char *oldpath, const char *newpath) {
log_esp3d("rename global %s to %s", oldpath, newpath);
#if defined(FILESYSTEM_FEATURE) || defined(SD_DEVICE)
uint8_t t = getFSType(oldpath);
if (t == FS_ROOT) {
log_esp3d_e("rename on root not allowed");
return false;
}
String o = getRealPath(oldpath);
String n = getRealPath(newpath);
#if defined(FILESYSTEM_FEATURE)
if (t == FS_FLASH) {
log_esp3d("rename FS %s to %s", n.c_str(), o.c_str());
return ESP_FileSystem::rename(o.c_str(), n.c_str());
}
#endif // FILESYSTEM_FEATURE
#if defined(SD_DEVICE)
if (t == FS_SD) {
log_esp3d("rename FS %s to %s", o.c_str(), n.c_str());
return ESP_SD::rename(o.c_str(), n.c_str());
}
#endif // SD_DEVICE
#endif // FILESYSTEM_FEATURE || SD_DEVICE
log_esp3d_e("Unknow FS, rename not allowed");
return false;
}
bool ESP_GBFS::mkdir(const char *path) {
#if defined(FILESYSTEM_FEATURE) || defined(SD_DEVICE)
uint8_t t = getFSType(path);
if (t == FS_ROOT) {
return false;
}
#if defined(FILESYSTEM_FEATURE)
if (t == FS_FLASH) {
return ESP_FileSystem::mkdir(getRealPath(path));
;
}
#endif // FILESYSTEM_FEATURE
#if defined(SD_DEVICE)
if (t == FS_SD) {
return ESP_SD::mkdir(getRealPath(path));
}
#endif // SD_DEVICE
#endif // FILESYSTEM_FEATURE || SD_DEVICE
return false;
}
bool ESP_GBFS::rmdir(const char *path) {
#if defined(FILESYSTEM_FEATURE) || defined(SD_DEVICE)
uint8_t t = getFSType(path);
if (t == FS_ROOT) {
return false;
}
#if defined(FILESYSTEM_FEATURE)
if (t == FS_FLASH) {
return ESP_FileSystem::rmdir(getRealPath(path));
}
#endif // FILESYSTEM_FEATURE
#if defined(SD_DEVICE)
if (t == FS_SD) {
return ESP_SD::rmdir(getRealPath(path));
;
}
#endif // SD_DEVICE
#endif // FILESYSTEM_FEATURE || SD_DEVICE
return false;
}
void ESP_GBFS::closeAll() {
getNextFS(true);
#if defined(FILESYSTEM_FEATURE)
ESP_FileSystem::closeAll();
#endif // FILESYSTEM_FEATURE
#if defined(SD_DEVICE)
ESP_SD::closeAll();
#endif // SD_DEVICE
}
ESP_GBFile ESP_GBFS::open(const char *path, uint8_t mode) {
ESP_GBFile f;
log_esp3d("open %s", path);
#if defined(FILESYSTEM_FEATURE) || defined(SD_DEVICE)
uint8_t t = getFSType(path);
log_esp3d("type %d", t);
if ((t == FS_ROOT) && (mode == ESP_FILE_READ)) {
f = ESP_GBFile(FS_ROOT, "/");
log_esp3d("root");
getNextFS(true);
}
#if defined(FILESYSTEM_FEATURE)
if (t == FS_FLASH) {
log_esp3d("open flash : %s", getRealPath(path));
f = ESP_FileSystem::open(getRealPath(path), mode);
}
#endif // FILESYSTEM_FEATURE
#if defined(SD_DEVICE)
if (t == FS_SD) {
log_esp3d("open SD : %s", getRealPath(path));
f = ESP_SD::open(getRealPath(path), mode);
}
#endif // SD_DEVICE
#endif // FILESYSTEM_FEATURE || SD_DEVICE
return f;
}
// Default File is no file
ESP_GBFile::ESP_GBFile() { _type = FS_UNKNOWN; }
// File handle for the root
ESP_GBFile::ESP_GBFile(uint8_t FS, const char *name) {
_type = FS;
_name = name;
}
// Handle for flash file
#ifdef FILESYSTEM_FEATURE
ESP_GBFile::ESP_GBFile(ESP_File &flashFile) {
_type = FS_FLASH;
_flashFile = flashFile;
#ifdef SD_DEVICE
_sdFile = ESP_SDFile();
#endif // SD_DEVICE
}
#endif // FILESYSTEM_FEATURE
// Handle for SD file
#ifdef SD_DEVICE
ESP_GBFile::ESP_GBFile(ESP_SDFile &sdFile) {
_type = FS_SD;
_sdFile = sdFile;
#ifdef FILESYSTEM_FEATURE
_flashFile = ESP_File();
#endif // FILESYSTEM_FEATURE
}
#endif // SD_DEVICE
// Destructor
ESP_GBFile::~ESP_GBFile() {}
ESP_GBFile::operator bool() const {
#if defined(FILESYSTEM_FEATURE) || defined(SD_DEVICE)
if (_type == FS_ROOT) {
return true;
}
#endif // FILESYSTEM_FEATURE || SD_DEVICE
#ifdef FILESYSTEM_FEATURE
if (_type == FS_FLASH) {
return _flashFile;
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (_type == FS_SD) {
return _sdFile;
}
#endif // SD_DEVICE
return false;
}
bool ESP_GBFile::seek(uint32_t pos, uint8_t mode) {
#if defined(FILESYSTEM_FEATURE) || defined(SD_DEVICE)
if (_type == FS_ROOT) {
return false;
}
#endif // FILESYSTEM_FEATURE || SD_DEVICE
#ifdef FILESYSTEM_FEATURE
if (_type == FS_FLASH) {
_flashFile.seek(pos, mode);
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (_type == FS_SD) {
return _sdFile.seek(pos, mode);
}
#endif // SD_DEVICE
return false;
}
void ESP_GBFile::close() {
#if defined(FILESYSTEM_FEATURE) || defined(SD_DEVICE)
if (_type == FS_ROOT) {
// TBD
}
#endif // FILESYSTEM_FEATURE || SD_DEVICE
#ifdef FILESYSTEM_FEATURE
if (_type == FS_FLASH) {
_flashFile.close();
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (_type == FS_SD) {
return _sdFile.close();
}
#endif // SD_DEVICE
}
bool ESP_GBFile::isOpen() {
#if defined(FILESYSTEM_FEATURE) || defined(SD_DEVICE)
if (_type == FS_ROOT) {
return true;
}
#endif // FILESYSTEM_FEATURE || SD_DEVICE
#ifdef FILESYSTEM_FEATURE
if (_type == FS_FLASH) {
return _flashFile.isOpen();
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (_type == FS_SD) {
return _sdFile.isOpen();
}
#endif // SD_DEVICE
return false;
}
const char *ESP_GBFile::name() const {
static String s;
#if defined(FILESYSTEM_FEATURE) || defined(SD_DEVICE)
if (_type == FS_ROOT) {
return _name.c_str();
}
#endif // FILESYSTEM_FEATURE || SD_DEVICE
#ifdef FILESYSTEM_FEATURE
if (_type == FS_FLASH) {
if (strcmp(_flashFile.name(), "/") == 0) {
s = ESP_FLASH_FS_HEADER;
s.remove(0, 1);
return s.c_str();
}
return _flashFile.name();
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (_type == FS_SD) {
if (strcmp(_sdFile.name(), "/") == 0) {
s = ESP_SD_FS_HEADER;
s.remove(0, 1);
return s.c_str();
}
return _sdFile.name();
}
#endif // SD_DEVICE
return "";
}
const char *ESP_GBFile::filename() const {
#if defined(FILESYSTEM_FEATURE) || defined(SD_DEVICE)
static String s;
if (_type == FS_ROOT) {
return "/";
}
#endif // FILESYSTEM_FEATURE || SD_DEVICE
#ifdef FILESYSTEM_FEATURE
if (_type == FS_FLASH) {
s = ESP_FLASH_FS_HEADER;
s += _flashFile.filename();
return s.c_str();
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (_type == FS_SD) {
s = ESP_SD_FS_HEADER;
s += s += _sdFile.filename();
return s.c_str();
}
#endif // SD_DEVICE
return "";
}
bool ESP_GBFile::isDirectory() {
#if defined(FILESYSTEM_FEATURE) || defined(SD_DEVICE)
if (_type == FS_ROOT) {
return true;
}
#endif // FILESYSTEM_FEATURE || SD_DEVICE
#ifdef FILESYSTEM_FEATURE
if (_type == FS_FLASH) {
return _flashFile.isDirectory();
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (_type == FS_SD) {
return _sdFile.isDirectory();
}
#endif // SD_DEVICE
return false;
}
size_t ESP_GBFile::size() {
#if defined(FILESYSTEM_FEATURE) || defined(SD_DEVICE)
if (_type == FS_ROOT) {
return 0;
}
#endif // FILESYSTEM_FEATURE || SD_DEVICE
#ifdef FILESYSTEM_FEATURE
if (_type == FS_FLASH) {
return _flashFile.size();
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (_type == FS_SD) {
return _sdFile.size();
}
#endif // SD_DEVICE
return 0;
}
time_t ESP_GBFile::getLastWrite() {
if (_type == FS_FLASH) {
return _flashFile.getLastWrite();
}
#ifdef SD_DEVICE
if (_type == FS_SD) {
return _sdFile.getLastWrite();
}
#endif // SD_DEVICE
return 0;
}
int ESP_GBFile::available() {
#if defined(FILESYSTEM_FEATURE) || defined(SD_DEVICE)
if (_type == FS_ROOT) {
return 0;
}
#endif // FILESYSTEM_FEATURE || SD_DEVICE
#ifdef FILESYSTEM_FEATURE
if (_type == FS_FLASH) {
return _flashFile.available();
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (_type == FS_SD) {
return _sdFile.available();
}
#endif // SD_DEVICE
return 0;
}
size_t ESP_GBFile::write(uint8_t i) {
#if defined(FILESYSTEM_FEATURE) || defined(SD_DEVICE)
if (_type == FS_ROOT) {
return 0;
}
#endif // FILESYSTEM_FEATURE || SD_DEVICE
#ifdef FILESYSTEM_FEATURE
if (_type == FS_FLASH) {
return _flashFile.write(i);
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (_type == FS_SD) {
return _sdFile.write(i);
}
#endif // SD_DEVICE
return 0;
}
size_t ESP_GBFile::write(const uint8_t *buf, size_t size) {
#if defined(FILESYSTEM_FEATURE) || defined(SD_DEVICE)
if (_type == FS_ROOT) {
return 0;
}
#endif // FILESYSTEM_FEATURE || SD_DEVICE
#ifdef FILESYSTEM_FEATURE
if (_type == FS_FLASH) {
return _flashFile.write(buf, size);
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (_type == FS_SD) {
return _sdFile.write(buf, size);
}
#endif // SD_DEVICE
return 0;
}
int ESP_GBFile::read() {
#if defined(FILESYSTEM_FEATURE) || defined(SD_DEVICE)
if (_type == FS_ROOT) {
return -1;
}
#endif // FILESYSTEM_FEATURE || SD_DEVICE
#ifdef FILESYSTEM_FEATURE
if (_type == FS_FLASH) {
return _flashFile.read();
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (_type == FS_SD) {
return _sdFile.read();
}
#endif // SD_DEVICE
return -1;
}
size_t ESP_GBFile::read(uint8_t *buf, size_t size) {
#if defined(FILESYSTEM_FEATURE) || defined(SD_DEVICE)
if (_type == FS_ROOT) {
return -1;
}
#endif // FILESYSTEM_FEATURE || SD_DEVICE
#ifdef FILESYSTEM_FEATURE
if (_type == FS_FLASH) {
return _flashFile.read(buf, size);
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (_type == FS_SD) {
return _sdFile.read(buf, size);
}
#endif // SD_DEVICE
return -1;
}
void ESP_GBFile::flush() {
#ifdef FILESYSTEM_FEATURE
if (_type == FS_FLASH) {
return _flashFile.flush();
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (_type == FS_SD) {
return _sdFile.flush();
}
#endif // SD_DEVICE
return;
}
ESP_GBFile &ESP_GBFile::operator=(const ESP_GBFile &other) {
#ifdef FILESYSTEM_FEATURE
_flashFile = other._flashFile;
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
_sdFile = other._sdFile;
#endif // SD_DEVICE
_type = other._type;
_name = other._name;
return *this;
}
#ifdef FILESYSTEM_FEATURE
ESP_GBFile &ESP_GBFile::operator=(const ESP_File &other) {
_flashFile = other;
#ifdef SD_DEVICE
_sdFile = ESP_SDFile();
#endif // SD_DEVICE
_type = FS_FLASH;
return *this;
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
ESP_GBFile &ESP_GBFile::operator=(const ESP_SDFile &other) {
#ifdef FILESYSTEM_FEATURE
_flashFile = ESP_File();
#endif // FILESYSTEM_FEATURE
_sdFile = other;
_type = FS_SD;
return *this;
}
#endif // SD_DEVICE
const char *ESP_GBFS::getNextFS(bool reset) {
static uint8_t index = 0;
if (reset) {
index = 0;
if (_nbFS == 0) {
#ifdef FILESYSTEM_FEATURE
_rootlist[_nbFS] = ESP_FLASH_FS_HEADER;
_nbFS++;
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
_rootlist[_nbFS] = ESP_SD_FS_HEADER;
_nbFS++;
#endif // SD_DEVICE
}
return "";
}
if (index < _nbFS) {
uint8_t i = index;
index++;
return _rootlist[i].c_str();
}
index = 0;
return "";
}
ESP_GBFile ESP_GBFile::openNextFile() {
ESP_GBFile f;
if (_type == FS_ROOT) {
String path = ESP_GBFS::getNextFS();
if (path.length() > 0) {
f = ESP_GBFile(FS_ROOT, &path[1]);
}
}
#ifdef FILESYSTEM_FEATURE
if (_type == FS_FLASH) {
f = _flashFile.openNextFile();
}
#endif // FILESYSTEM_FEATURE
#ifdef SD_DEVICE
if (_type == FS_SD) {
f = _sdFile.openNextFile();
}
#endif // SD_DEVICE
return f;
}
#endif // GLOBAL_FILESYSTEM_FEATURE