mirror of
https://github.com/esp8266/Arduino.git
synced 2025-07-16 00:43:00 +03:00
FileSystem: interface changes and some additions
- rename mount to begin to be more in line with other libraries - add rename and remove methods - remove freestanding functions (mount,open,openDir) from public API until that part is ready - fix resource leak in SPIFFSDirImpl
This commit is contained in:
@ -143,7 +143,16 @@ bool Dir::next() {
|
||||
return _impl->next();
|
||||
}
|
||||
|
||||
bool FS::begin() {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
return _impl->begin();
|
||||
}
|
||||
|
||||
File FS::open(const String& path, const char* mode) {
|
||||
return open(path.c_str(), mode);
|
||||
}
|
||||
|
||||
File FS::open(const char* path, const char* mode) {
|
||||
if (!_impl) {
|
||||
@ -160,46 +169,40 @@ File FS::open(const char* path, const char* mode) {
|
||||
return File(_impl->open(path, om, am));
|
||||
}
|
||||
|
||||
File FS::open(const String& path, const char* mode) {
|
||||
return FS::open(path.c_str(), mode);
|
||||
}
|
||||
|
||||
Dir FS::openDir(const char* path) {
|
||||
if (!_impl) {
|
||||
return Dir();
|
||||
}
|
||||
|
||||
return Dir(_impl->openDir(path));
|
||||
}
|
||||
|
||||
Dir FS::openDir(const String& path) {
|
||||
return FS::openDir(path.c_str());
|
||||
return openDir(path.c_str());
|
||||
}
|
||||
|
||||
struct MountEntry {
|
||||
FSImplPtr fs;
|
||||
String path;
|
||||
MountEntry* next;
|
||||
};
|
||||
|
||||
static MountEntry* s_mounted = nullptr;
|
||||
|
||||
template<>
|
||||
bool mount<FS>(FS& fs, const char* mountPoint) {
|
||||
FSImplPtr p = fs._impl;
|
||||
if (!p || !p->mount()) {
|
||||
DEBUGV("FSImpl mount failed\r\n");
|
||||
bool FS::remove(const char* path) {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MountEntry* entry = new MountEntry;
|
||||
entry->fs = p;
|
||||
entry->path = mountPoint;
|
||||
entry->next = s_mounted;
|
||||
s_mounted = entry;
|
||||
return true;
|
||||
return _impl->remove(path);
|
||||
}
|
||||
|
||||
bool FS::remove(const String& path) {
|
||||
return remove(path.c_str());
|
||||
}
|
||||
|
||||
bool FS::rename(const char* pathFrom, const char* pathTo) {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
return _impl->rename(pathFrom, pathTo);
|
||||
}
|
||||
|
||||
bool FS::rename(const String& pathFrom, const String& pathTo) {
|
||||
return rename(pathFrom.c_str(), pathTo.c_str());
|
||||
}
|
||||
|
||||
|
||||
static bool sflags(const char* mode, OpenMode& om, AccessMode& am) {
|
||||
switch (mode[0]) {
|
||||
case 'r':
|
||||
@ -228,3 +231,80 @@ static bool sflags(const char* mode, OpenMode& om, AccessMode& am) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if defined(FS_FREESTANDING_FUNCTIONS)
|
||||
|
||||
/*
|
||||
TODO: move these functions to public API:
|
||||
*/
|
||||
File open(const char* path, const char* mode);
|
||||
File open(String& path, const char* mode);
|
||||
|
||||
Dir openDir(const char* path);
|
||||
Dir openDir(String& path);
|
||||
|
||||
template<>
|
||||
bool mount<FS>(FS& fs, const char* mountPoint);
|
||||
/*
|
||||
*/
|
||||
|
||||
|
||||
struct MountEntry {
|
||||
FSImplPtr fs;
|
||||
String path;
|
||||
MountEntry* next;
|
||||
};
|
||||
|
||||
static MountEntry* s_mounted = nullptr;
|
||||
|
||||
template<>
|
||||
bool mount<FS>(FS& fs, const char* mountPoint) {
|
||||
FSImplPtr p = fs._impl;
|
||||
if (!p || !p->mount()) {
|
||||
DEBUGV("FSImpl mount failed\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
!make sure mountPoint has trailing '/' here
|
||||
|
||||
MountEntry* entry = new MountEntry;
|
||||
entry->fs = p;
|
||||
entry->path = mountPoint;
|
||||
entry->next = s_mounted;
|
||||
s_mounted = entry;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
iterate over MountEntries and look for the ones which match the path
|
||||
*/
|
||||
File open(const char* path, const char* mode) {
|
||||
OpenMode om;
|
||||
AccessMode am;
|
||||
if (!sflags(mode, om, am)) {
|
||||
DEBUGV("open: invalid mode `%s`\r\n", mode);
|
||||
return File();
|
||||
}
|
||||
|
||||
for (MountEntry* entry = s_mounted; entry; entry = entry->next) {
|
||||
size_t offset = entry->path.length();
|
||||
if (strstr(path, entry->path.c_str())) {
|
||||
File result = entry->fs->open(path + offset);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return File();
|
||||
}
|
||||
|
||||
File open(const String& path, const char* mode) {
|
||||
return FS::open(path.c_str(), mode);
|
||||
}
|
||||
|
||||
Dir openDir(const String& path) {
|
||||
return openDir(path.c_str());
|
||||
}
|
||||
#endif
|
||||
|
@ -24,6 +24,9 @@
|
||||
#include <Arduino.h>
|
||||
#include <memory>
|
||||
|
||||
class File;
|
||||
class Dir;
|
||||
|
||||
class FileImpl;
|
||||
typedef std::shared_ptr<FileImpl> FileImplPtr;
|
||||
class FSImpl;
|
||||
@ -82,25 +85,26 @@ class FS
|
||||
{
|
||||
public:
|
||||
FS(FSImplPtr impl) : _impl(impl) { }
|
||||
|
||||
bool begin();
|
||||
|
||||
File open(const char* path, const char* mode);
|
||||
File open(const String& path, const char* mode);
|
||||
|
||||
Dir openDir(const char* path);
|
||||
Dir openDir(const String& path);
|
||||
|
||||
bool remove(const char* path);
|
||||
bool remove(const String& path);
|
||||
|
||||
bool rename(const char* pathFrom, const char* pathTo);
|
||||
bool rename(const String& pathFrom, const String& pathTo);
|
||||
|
||||
protected:
|
||||
FSImplPtr _impl;
|
||||
|
||||
template <typename Tfs>
|
||||
friend bool mount(Tfs& fs, const char* mountPoint);
|
||||
};
|
||||
|
||||
extern FS SPIFFS;
|
||||
|
||||
template<>
|
||||
bool mount<FS>(FS& fs, const char* mountPoint);
|
||||
|
||||
File open(const char* path, const char* mode);
|
||||
|
||||
Dir openDir(const char* path);
|
||||
|
||||
#endif //FS_H
|
||||
|
@ -50,6 +50,7 @@ enum AccessMode {
|
||||
|
||||
class DirImpl {
|
||||
public:
|
||||
virtual ~DirImpl() { }
|
||||
virtual FileImplPtr openFile(OpenMode openMode, AccessMode accessMode) = 0;
|
||||
virtual const char* fileName() = 0;
|
||||
virtual bool next() = 0;
|
||||
@ -57,9 +58,11 @@ public:
|
||||
|
||||
class FSImpl {
|
||||
public:
|
||||
virtual bool begin() = 0;
|
||||
virtual FileImplPtr open(const char* path, OpenMode openMode, AccessMode accessMode) = 0;
|
||||
virtual DirImplPtr openDir(const char* path) = 0;
|
||||
virtual bool mount() = 0;
|
||||
virtual bool rename(const char* pathFrom, const char* pathTo) = 0;
|
||||
virtual bool remove(const char* path) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -57,21 +57,43 @@ public:
|
||||
|
||||
DirImplPtr openDir(const char* path) override;
|
||||
|
||||
bool mount() override {
|
||||
bool rename(const char* pathFrom, const char* pathTo) override {
|
||||
char tmpNameFrom[SPIFFS_OBJ_NAME_LEN];
|
||||
strlcpy(tmpNameFrom, pathFrom, sizeof(tmpNameFrom));
|
||||
char tmpNameTo[SPIFFS_OBJ_NAME_LEN];
|
||||
strlcpy(tmpNameTo, pathTo, sizeof(tmpNameTo));
|
||||
auto rc = SPIFFS_rename(&_fs, tmpNameFrom, tmpNameTo);
|
||||
if (rc != SPIFFS_OK) {
|
||||
DEBUGV("SPIFFS_rename: rc=%d, from=`%s`, to=`%s`\r\n", rc,
|
||||
pathFrom, pathTo);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool remove(const char* path) override {
|
||||
char tmpName[SPIFFS_OBJ_NAME_LEN];
|
||||
strlcpy(tmpName, path, sizeof(tmpName));
|
||||
auto rc = SPIFFS_remove(&_fs, tmpName);
|
||||
if (rc != SPIFFS_OK) {
|
||||
DEBUGV("SPIFFS_remove: rc=%d path=`%s`\r\n", rc, path);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool begin() override {
|
||||
if (SPIFFS_mounted(&_fs) != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_tryMount()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto rc = SPIFFS_format(&_fs);
|
||||
if (rc != SPIFFS_OK) {
|
||||
DEBUGV("SPIFFS_format: rc=%d, err=%d\r\n", rc, _fs.err_code);
|
||||
return false;
|
||||
}
|
||||
|
||||
return _tryMount();
|
||||
}
|
||||
|
||||
@ -252,6 +274,10 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
~SPIFFSDirImpl() override {
|
||||
SPIFFS_closedir(&_dir);
|
||||
}
|
||||
|
||||
FileImplPtr openFile(OpenMode openMode, AccessMode accessMode) override {
|
||||
if (!_valid) {
|
||||
return FileImplPtr();
|
||||
|
Reference in New Issue
Block a user