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();
|
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) {
|
File FS::open(const char* path, const char* mode) {
|
||||||
if (!_impl) {
|
if (!_impl) {
|
||||||
@ -160,46 +169,40 @@ File FS::open(const char* path, const char* mode) {
|
|||||||
return File(_impl->open(path, om, am));
|
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) {
|
Dir FS::openDir(const char* path) {
|
||||||
if (!_impl) {
|
if (!_impl) {
|
||||||
return Dir();
|
return Dir();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Dir(_impl->openDir(path));
|
return Dir(_impl->openDir(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
Dir FS::openDir(const String& path) {
|
Dir FS::openDir(const String& path) {
|
||||||
return FS::openDir(path.c_str());
|
return openDir(path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MountEntry {
|
bool FS::remove(const char* path) {
|
||||||
FSImplPtr fs;
|
if (!_impl) {
|
||||||
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
return _impl->remove(path);
|
||||||
MountEntry* entry = new MountEntry;
|
|
||||||
entry->fs = p;
|
|
||||||
entry->path = mountPoint;
|
|
||||||
entry->next = s_mounted;
|
|
||||||
s_mounted = entry;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
static bool sflags(const char* mode, OpenMode& om, AccessMode& am) {
|
||||||
switch (mode[0]) {
|
switch (mode[0]) {
|
||||||
case 'r':
|
case 'r':
|
||||||
@ -228,3 +231,80 @@ static bool sflags(const char* mode, OpenMode& om, AccessMode& am) {
|
|||||||
}
|
}
|
||||||
return true;
|
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 <Arduino.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
class File;
|
||||||
|
class Dir;
|
||||||
|
|
||||||
class FileImpl;
|
class FileImpl;
|
||||||
typedef std::shared_ptr<FileImpl> FileImplPtr;
|
typedef std::shared_ptr<FileImpl> FileImplPtr;
|
||||||
class FSImpl;
|
class FSImpl;
|
||||||
@ -82,25 +85,26 @@ class FS
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FS(FSImplPtr impl) : _impl(impl) { }
|
FS(FSImplPtr impl) : _impl(impl) { }
|
||||||
|
|
||||||
|
bool begin();
|
||||||
|
|
||||||
File open(const char* path, const char* mode);
|
File open(const char* path, const char* mode);
|
||||||
File open(const String& path, const char* mode);
|
File open(const String& path, const char* mode);
|
||||||
|
|
||||||
Dir openDir(const char* path);
|
Dir openDir(const char* path);
|
||||||
Dir openDir(const String& 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:
|
protected:
|
||||||
FSImplPtr _impl;
|
FSImplPtr _impl;
|
||||||
|
|
||||||
template <typename Tfs>
|
|
||||||
friend bool mount(Tfs& fs, const char* mountPoint);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern FS SPIFFS;
|
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
|
#endif //FS_H
|
||||||
|
@ -50,6 +50,7 @@ enum AccessMode {
|
|||||||
|
|
||||||
class DirImpl {
|
class DirImpl {
|
||||||
public:
|
public:
|
||||||
|
virtual ~DirImpl() { }
|
||||||
virtual FileImplPtr openFile(OpenMode openMode, AccessMode accessMode) = 0;
|
virtual FileImplPtr openFile(OpenMode openMode, AccessMode accessMode) = 0;
|
||||||
virtual const char* fileName() = 0;
|
virtual const char* fileName() = 0;
|
||||||
virtual bool next() = 0;
|
virtual bool next() = 0;
|
||||||
@ -57,9 +58,11 @@ public:
|
|||||||
|
|
||||||
class FSImpl {
|
class FSImpl {
|
||||||
public:
|
public:
|
||||||
|
virtual bool begin() = 0;
|
||||||
virtual FileImplPtr open(const char* path, OpenMode openMode, AccessMode accessMode) = 0;
|
virtual FileImplPtr open(const char* path, OpenMode openMode, AccessMode accessMode) = 0;
|
||||||
virtual DirImplPtr openDir(const char* path) = 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;
|
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) {
|
if (SPIFFS_mounted(&_fs) != 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_tryMount()) {
|
if (_tryMount()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto rc = SPIFFS_format(&_fs);
|
auto rc = SPIFFS_format(&_fs);
|
||||||
if (rc != SPIFFS_OK) {
|
if (rc != SPIFFS_OK) {
|
||||||
DEBUGV("SPIFFS_format: rc=%d, err=%d\r\n", rc, _fs.err_code);
|
DEBUGV("SPIFFS_format: rc=%d, err=%d\r\n", rc, _fs.err_code);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _tryMount();
|
return _tryMount();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,6 +274,10 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~SPIFFSDirImpl() override {
|
||||||
|
SPIFFS_closedir(&_dir);
|
||||||
|
}
|
||||||
|
|
||||||
FileImplPtr openFile(OpenMode openMode, AccessMode accessMode) override {
|
FileImplPtr openFile(OpenMode openMode, AccessMode accessMode) override {
|
||||||
if (!_valid) {
|
if (!_valid) {
|
||||||
return FileImplPtr();
|
return FileImplPtr();
|
||||||
|
Reference in New Issue
Block a user