forked from espressif/arduino-esp32
Updated to newest IDF with new GCC
This commit is contained in:
@ -23,10 +23,7 @@ set(CORE_SRCS
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(LIBRARY_SRCS
|
set(LIBRARY_SRCS
|
||||||
libraries/FS/src/FS.cpp
|
|
||||||
libraries/FS/src/vfs_api.cpp
|
|
||||||
libraries/SPI/src/SPI.cpp
|
libraries/SPI/src/SPI.cpp
|
||||||
libraries/SPIFFS/src/SPIFFS.cpp
|
|
||||||
libraries/Wire/src/Wire.cpp
|
libraries/Wire/src/Wire.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -34,15 +31,13 @@ set(LIBRARY_SRCS
|
|||||||
set(includedirs
|
set(includedirs
|
||||||
variants/esp32/
|
variants/esp32/
|
||||||
cores/esp32/
|
cores/esp32/
|
||||||
libraries/FS/src
|
|
||||||
libraries/SPI/src
|
libraries/SPI/src
|
||||||
libraries/SPIFFS/src
|
|
||||||
libraries/Wire/src
|
libraries/Wire/src
|
||||||
)
|
)
|
||||||
|
|
||||||
set(srcs ${CORE_SRCS} ${LIBRARY_SRCS} ${BLE_SRCS})
|
set(srcs ${CORE_SRCS} ${LIBRARY_SRCS} ${BLE_SRCS})
|
||||||
set(requires spi_flash mbedtls esp_adc_cal wifi_provisioning)
|
set(requires spi_flash mbedtls esp_adc_cal wifi_provisioning)
|
||||||
set(priv_requires nvs_flash spiffs bootloader_support tinyusb espcpputils fmt)
|
set(priv_requires nvs_flash bootloader_support tinyusb espcpputils fmt)
|
||||||
|
|
||||||
idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires})
|
idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires})
|
||||||
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
name=FS
|
|
||||||
version=1.0
|
|
||||||
author=Hristo Gochkov, Ivan Grokhtkov
|
|
||||||
maintainer=Hristo Gochkov <hristo@espressif.com>
|
|
||||||
sentence=ESP32 File System
|
|
||||||
paragraph=
|
|
||||||
category=Data Storage
|
|
||||||
url=
|
|
||||||
architectures=esp32
|
|
@ -1,269 +0,0 @@
|
|||||||
/*
|
|
||||||
FS.cpp - file system wrapper
|
|
||||||
Copyright (c) 2015 Ivan Grokhotkov. All rights reserved.
|
|
||||||
This file is part of the esp8266 core for Arduino environment.
|
|
||||||
|
|
||||||
This library 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 library 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 library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "FS.h"
|
|
||||||
#include "FSImpl.h"
|
|
||||||
|
|
||||||
using namespace fs;
|
|
||||||
|
|
||||||
size_t File::write(uint8_t c)
|
|
||||||
{
|
|
||||||
if (!_p) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _p->write(&c, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t File::getLastWrite()
|
|
||||||
{
|
|
||||||
if (!_p) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _p->getLastWrite();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t File::write(const uint8_t *buf, size_t size)
|
|
||||||
{
|
|
||||||
if (!_p) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _p->write(buf, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
int File::available()
|
|
||||||
{
|
|
||||||
if (!_p) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _p->size() - _p->position();
|
|
||||||
}
|
|
||||||
|
|
||||||
int File::read()
|
|
||||||
{
|
|
||||||
if (!_p) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t result;
|
|
||||||
if (_p->read(&result, 1) != 1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t File::read(uint8_t* buf, size_t size)
|
|
||||||
{
|
|
||||||
if (!_p) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _p->read(buf, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
int File::peek()
|
|
||||||
{
|
|
||||||
if (!_p) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t curPos = _p->position();
|
|
||||||
int result = read();
|
|
||||||
seek(curPos, SeekSet);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void File::flush()
|
|
||||||
{
|
|
||||||
if (!_p) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_p->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool File::seek(uint32_t pos, SeekMode mode)
|
|
||||||
{
|
|
||||||
if (!_p) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _p->seek(pos, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t File::position() const
|
|
||||||
{
|
|
||||||
if (!_p) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _p->position();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t File::size() const
|
|
||||||
{
|
|
||||||
if (!_p) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _p->size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void File::close()
|
|
||||||
{
|
|
||||||
if (_p) {
|
|
||||||
_p->close();
|
|
||||||
_p = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
File::operator bool() const
|
|
||||||
{
|
|
||||||
return !!_p;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* File::name() const
|
|
||||||
{
|
|
||||||
if (!_p) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _p->name();
|
|
||||||
}
|
|
||||||
|
|
||||||
//to implement
|
|
||||||
bool File::isDirectory(void)
|
|
||||||
{
|
|
||||||
if (!_p) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return _p->isDirectory();
|
|
||||||
}
|
|
||||||
|
|
||||||
File File::openNextFile(const char* mode)
|
|
||||||
{
|
|
||||||
if (!_p) {
|
|
||||||
return File();
|
|
||||||
}
|
|
||||||
return _p->openNextFile(mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void File::rewindDirectory(void)
|
|
||||||
{
|
|
||||||
if (!_p) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_p->rewindDirectory();
|
|
||||||
}
|
|
||||||
|
|
||||||
File FS::open(const std::string& path, const char* mode)
|
|
||||||
{
|
|
||||||
return open(path.c_str(), mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
File FS::open(const char* path, const char* mode)
|
|
||||||
{
|
|
||||||
if (!_impl) {
|
|
||||||
return File();
|
|
||||||
}
|
|
||||||
|
|
||||||
return File(_impl->open(path, mode));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FS::exists(const char* path)
|
|
||||||
{
|
|
||||||
if (!_impl) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return _impl->exists(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FS::exists(const std::string& path)
|
|
||||||
{
|
|
||||||
return exists(path.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FS::remove(const char* path)
|
|
||||||
{
|
|
||||||
if (!_impl) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return _impl->remove(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FS::remove(const std::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 std::string& pathFrom, const std::string& pathTo)
|
|
||||||
{
|
|
||||||
return rename(pathFrom.c_str(), pathTo.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool FS::mkdir(const char *path)
|
|
||||||
{
|
|
||||||
if (!_impl) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return _impl->mkdir(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FS::mkdir(const std::string &path)
|
|
||||||
{
|
|
||||||
return mkdir(path.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FS::rmdir(const char *path)
|
|
||||||
{
|
|
||||||
if (!_impl) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return _impl->rmdir(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FS::rmdir(const std::string &path)
|
|
||||||
{
|
|
||||||
return rmdir(path.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FSImpl::mountpoint(const char * mp)
|
|
||||||
{
|
|
||||||
_mountpoint = mp;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char * FSImpl::mountpoint()
|
|
||||||
{
|
|
||||||
return _mountpoint;
|
|
||||||
}
|
|
@ -1,124 +0,0 @@
|
|||||||
/*
|
|
||||||
FS.h - file system wrapper
|
|
||||||
Copyright (c) 2015 Ivan Grokhotkov. All rights reserved.
|
|
||||||
This file is part of the esp8266 core for Arduino environment.
|
|
||||||
|
|
||||||
This library 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 library 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 library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FS_H
|
|
||||||
#define FS_H
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace fs
|
|
||||||
{
|
|
||||||
|
|
||||||
#define FILE_READ "r"
|
|
||||||
#define FILE_WRITE "w"
|
|
||||||
#define FILE_APPEND "a"
|
|
||||||
|
|
||||||
class File;
|
|
||||||
|
|
||||||
class FileImpl;
|
|
||||||
typedef std::shared_ptr<FileImpl> FileImplPtr;
|
|
||||||
class FSImpl;
|
|
||||||
typedef std::shared_ptr<FSImpl> FSImplPtr;
|
|
||||||
|
|
||||||
enum SeekMode {
|
|
||||||
SeekSet = 0,
|
|
||||||
SeekCur = 1,
|
|
||||||
SeekEnd = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
class File
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
File(FileImplPtr p = FileImplPtr()) : _p(p) {
|
|
||||||
//_timeout = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t write(uint8_t);
|
|
||||||
size_t write(const uint8_t *buf, size_t size);
|
|
||||||
int available();
|
|
||||||
int read();
|
|
||||||
int peek();
|
|
||||||
void flush();
|
|
||||||
size_t read(uint8_t* buf, size_t size);
|
|
||||||
size_t readBytes(char *buffer, size_t length)
|
|
||||||
{
|
|
||||||
return read((uint8_t*)buffer, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool seek(uint32_t pos, SeekMode mode);
|
|
||||||
bool seek(uint32_t pos)
|
|
||||||
{
|
|
||||||
return seek(pos, SeekSet);
|
|
||||||
}
|
|
||||||
size_t position() const;
|
|
||||||
size_t size() const;
|
|
||||||
void close();
|
|
||||||
operator bool() const;
|
|
||||||
time_t getLastWrite();
|
|
||||||
const char* name() const;
|
|
||||||
|
|
||||||
bool isDirectory(void);
|
|
||||||
File openNextFile(const char* mode = FILE_READ);
|
|
||||||
void rewindDirectory(void);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
FileImplPtr _p;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FS
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FS(FSImplPtr impl) : _impl(impl) { }
|
|
||||||
|
|
||||||
File open(const char* path, const char* mode = FILE_READ);
|
|
||||||
File open(const std::string& path, const char* mode = FILE_READ);
|
|
||||||
|
|
||||||
bool exists(const char* path);
|
|
||||||
bool exists(const std::string& path);
|
|
||||||
|
|
||||||
bool remove(const char* path);
|
|
||||||
bool remove(const std::string& path);
|
|
||||||
|
|
||||||
bool rename(const char* pathFrom, const char* pathTo);
|
|
||||||
bool rename(const std::string& pathFrom, const std::string& pathTo);
|
|
||||||
|
|
||||||
bool mkdir(const char *path);
|
|
||||||
bool mkdir(const std::string &path);
|
|
||||||
|
|
||||||
bool rmdir(const char *path);
|
|
||||||
bool rmdir(const std::string &path);
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
|
||||||
FSImplPtr _impl;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace fs
|
|
||||||
|
|
||||||
#ifndef FS_NO_GLOBALS
|
|
||||||
using fs::FS;
|
|
||||||
using fs::File;
|
|
||||||
using fs::SeekMode;
|
|
||||||
using fs::SeekSet;
|
|
||||||
using fs::SeekCur;
|
|
||||||
using fs::SeekEnd;
|
|
||||||
#endif //FS_NO_GLOBALS
|
|
||||||
|
|
||||||
#endif //FS_H
|
|
@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
FSImpl.h - base file system interface
|
|
||||||
Copyright (c) 2015 Ivan Grokhotkov. All rights reserved.
|
|
||||||
This file is part of the esp8266 core for Arduino environment.
|
|
||||||
|
|
||||||
This library 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 library 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 library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
#ifndef FSIMPL_H
|
|
||||||
#define FSIMPL_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
namespace fs
|
|
||||||
{
|
|
||||||
|
|
||||||
class FileImpl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~FileImpl() { }
|
|
||||||
virtual size_t write(const uint8_t *buf, size_t size) = 0;
|
|
||||||
virtual size_t read(uint8_t* buf, size_t size) = 0;
|
|
||||||
virtual void flush() = 0;
|
|
||||||
virtual bool seek(uint32_t pos, SeekMode mode) = 0;
|
|
||||||
virtual size_t position() const = 0;
|
|
||||||
virtual size_t size() const = 0;
|
|
||||||
virtual void close() = 0;
|
|
||||||
virtual time_t getLastWrite() = 0;
|
|
||||||
virtual const char* name() const = 0;
|
|
||||||
virtual bool isDirectory(void) = 0;
|
|
||||||
virtual FileImplPtr openNextFile(const char* mode) = 0;
|
|
||||||
virtual void rewindDirectory(void) = 0;
|
|
||||||
virtual operator bool() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FSImpl
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
const char * _mountpoint;
|
|
||||||
public:
|
|
||||||
FSImpl() : _mountpoint(NULL) { }
|
|
||||||
virtual ~FSImpl() { }
|
|
||||||
virtual FileImplPtr open(const char* path, const char* mode) = 0;
|
|
||||||
virtual bool exists(const char* path) = 0;
|
|
||||||
virtual bool rename(const char* pathFrom, const char* pathTo) = 0;
|
|
||||||
virtual bool remove(const char* path) = 0;
|
|
||||||
virtual bool mkdir(const char *path) = 0;
|
|
||||||
virtual bool rmdir(const char *path) = 0;
|
|
||||||
void mountpoint(const char *);
|
|
||||||
const char * mountpoint();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace fs
|
|
||||||
|
|
||||||
#endif //FSIMPL_H
|
|
@ -1,436 +0,0 @@
|
|||||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include "vfs_api.h"
|
|
||||||
|
|
||||||
#include "esp32-hal-log.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
using namespace fs;
|
|
||||||
|
|
||||||
FileImplPtr VFSImpl::open(const char* path, const char* mode)
|
|
||||||
{
|
|
||||||
if(!_mountpoint) {
|
|
||||||
log_e("File system is not mounted");
|
|
||||||
return FileImplPtr();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!path || path[0] != '/') {
|
|
||||||
log_e("%s does not start with /", path);
|
|
||||||
return FileImplPtr();
|
|
||||||
}
|
|
||||||
|
|
||||||
char * temp = (char *)malloc(strlen(path)+strlen(_mountpoint)+2);
|
|
||||||
if(!temp) {
|
|
||||||
log_e("malloc failed");
|
|
||||||
return FileImplPtr();
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(temp,"%s%s", _mountpoint, path);
|
|
||||||
|
|
||||||
struct stat st;
|
|
||||||
//file lound
|
|
||||||
if(!stat(temp, &st)) {
|
|
||||||
free(temp);
|
|
||||||
if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) {
|
|
||||||
return std::make_shared<VFSFileImpl>(this, path, mode);
|
|
||||||
}
|
|
||||||
log_e("%s has wrong mode 0x%08X", path, st.st_mode);
|
|
||||||
return FileImplPtr();
|
|
||||||
}
|
|
||||||
|
|
||||||
//file not found but mode permits creation
|
|
||||||
if(mode && mode[0] != 'r') {
|
|
||||||
free(temp);
|
|
||||||
return std::make_shared<VFSFileImpl>(this, path, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
//try to open this as directory (might be mount point)
|
|
||||||
DIR * d = opendir(temp);
|
|
||||||
if(d) {
|
|
||||||
closedir(d);
|
|
||||||
free(temp);
|
|
||||||
return std::make_shared<VFSFileImpl>(this, path, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
log_e("%s does not exist", temp);
|
|
||||||
free(temp);
|
|
||||||
return FileImplPtr();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VFSImpl::exists(const char* path)
|
|
||||||
{
|
|
||||||
if(!_mountpoint) {
|
|
||||||
log_e("File system is not mounted");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
VFSFileImpl f(this, path, "r");
|
|
||||||
if(f) {
|
|
||||||
f.close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VFSImpl::rename(const char* pathFrom, const char* pathTo)
|
|
||||||
{
|
|
||||||
if(!_mountpoint) {
|
|
||||||
log_e("File system is not mounted");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!pathFrom || pathFrom[0] != '/' || !pathTo || pathTo[0] != '/') {
|
|
||||||
log_e("bad arguments");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(!exists(pathFrom)) {
|
|
||||||
log_e("%s does not exists", pathFrom);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
char * temp1 = (char *)malloc(strlen(pathFrom)+strlen(_mountpoint)+1);
|
|
||||||
if(!temp1) {
|
|
||||||
log_e("malloc failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
char * temp2 = (char *)malloc(strlen(pathTo)+strlen(_mountpoint)+1);
|
|
||||||
if(!temp2) {
|
|
||||||
free(temp1);
|
|
||||||
log_e("malloc failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
sprintf(temp1,"%s%s", _mountpoint, pathFrom);
|
|
||||||
sprintf(temp2,"%s%s", _mountpoint, pathTo);
|
|
||||||
auto rc = ::rename(temp1, temp2);
|
|
||||||
free(temp1);
|
|
||||||
free(temp2);
|
|
||||||
return rc == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VFSImpl::remove(const char* path)
|
|
||||||
{
|
|
||||||
if(!_mountpoint) {
|
|
||||||
log_e("File system is not mounted");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!path || path[0] != '/') {
|
|
||||||
log_e("bad arguments");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
VFSFileImpl f(this, path, "r");
|
|
||||||
if(!f || f.isDirectory()) {
|
|
||||||
if(f) {
|
|
||||||
f.close();
|
|
||||||
}
|
|
||||||
log_e("%s does not exists or is directory", path);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
f.close();
|
|
||||||
|
|
||||||
char * temp = (char *)malloc(strlen(path)+strlen(_mountpoint)+1);
|
|
||||||
if(!temp) {
|
|
||||||
log_e("malloc failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
sprintf(temp,"%s%s", _mountpoint, path);
|
|
||||||
auto rc = unlink(temp);
|
|
||||||
free(temp);
|
|
||||||
return rc == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VFSImpl::mkdir(const char *path)
|
|
||||||
{
|
|
||||||
if(!_mountpoint) {
|
|
||||||
log_e("File system is not mounted");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
VFSFileImpl f(this, path, "r");
|
|
||||||
if(f && f.isDirectory()) {
|
|
||||||
f.close();
|
|
||||||
//log_w("%s already exists", path);
|
|
||||||
return true;
|
|
||||||
} else if(f) {
|
|
||||||
f.close();
|
|
||||||
log_e("%s is a file", path);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
char * temp = (char *)malloc(strlen(path)+strlen(_mountpoint)+1);
|
|
||||||
if(!temp) {
|
|
||||||
log_e("malloc failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
sprintf(temp,"%s%s", _mountpoint, path);
|
|
||||||
auto rc = ::mkdir(temp, ACCESSPERMS);
|
|
||||||
free(temp);
|
|
||||||
return rc == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VFSImpl::rmdir(const char *path)
|
|
||||||
{
|
|
||||||
if(!_mountpoint) {
|
|
||||||
log_e("File system is not mounted");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(_mountpoint, "/spiffs") == 0) {
|
|
||||||
log_e("rmdir is unnecessary in SPIFFS");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
VFSFileImpl f(this, path, "r");
|
|
||||||
if(!f || !f.isDirectory()) {
|
|
||||||
if(f) {
|
|
||||||
f.close();
|
|
||||||
}
|
|
||||||
log_e("%s does not exists or is a file", path);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
f.close();
|
|
||||||
|
|
||||||
char * temp = (char *)malloc(strlen(path)+strlen(_mountpoint)+1);
|
|
||||||
if(!temp) {
|
|
||||||
log_e("malloc failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
sprintf(temp,"%s%s", _mountpoint, path);
|
|
||||||
auto rc = ::rmdir(temp);
|
|
||||||
free(temp);
|
|
||||||
return rc == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
VFSFileImpl::VFSFileImpl(VFSImpl* fs, const char* path, const char* mode)
|
|
||||||
: _fs(fs)
|
|
||||||
, _f(NULL)
|
|
||||||
, _d(NULL)
|
|
||||||
, _path(NULL)
|
|
||||||
, _isDirectory(false)
|
|
||||||
, _written(false)
|
|
||||||
{
|
|
||||||
char * temp = (char *)malloc(strlen(path)+strlen(_fs->_mountpoint)+1);
|
|
||||||
if(!temp) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sprintf(temp,"%s%s", _fs->_mountpoint, path);
|
|
||||||
|
|
||||||
_path = strdup(path);
|
|
||||||
if(!_path) {
|
|
||||||
log_e("strdup(%s) failed", path);
|
|
||||||
free(temp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!stat(temp, &_stat)) {
|
|
||||||
//file found
|
|
||||||
if (S_ISREG(_stat.st_mode)) {
|
|
||||||
_isDirectory = false;
|
|
||||||
_f = fopen(temp, mode);
|
|
||||||
if(!_f) {
|
|
||||||
log_e("fopen(%s) failed", temp);
|
|
||||||
}
|
|
||||||
} else if(S_ISDIR(_stat.st_mode)) {
|
|
||||||
_isDirectory = true;
|
|
||||||
_d = opendir(temp);
|
|
||||||
if(!_d) {
|
|
||||||
log_e("opendir(%s) failed", temp);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log_e("Unknown type 0x%08X for file %s", ((_stat.st_mode)&_IFMT), temp);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//file not found
|
|
||||||
if(!mode || mode[0] == 'r') {
|
|
||||||
//try to open as directory
|
|
||||||
_d = opendir(temp);
|
|
||||||
if(_d) {
|
|
||||||
_isDirectory = true;
|
|
||||||
} else {
|
|
||||||
_isDirectory = false;
|
|
||||||
//log_w("stat(%s) failed", temp);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//lets create this new file
|
|
||||||
_isDirectory = false;
|
|
||||||
_f = fopen(temp, mode);
|
|
||||||
if(!_f) {
|
|
||||||
log_e("fopen(%s) failed", temp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
VFSFileImpl::~VFSFileImpl()
|
|
||||||
{
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VFSFileImpl::close()
|
|
||||||
{
|
|
||||||
if(_path) {
|
|
||||||
free(_path);
|
|
||||||
_path = NULL;
|
|
||||||
}
|
|
||||||
if(_isDirectory && _d) {
|
|
||||||
closedir(_d);
|
|
||||||
_d = NULL;
|
|
||||||
_isDirectory = false;
|
|
||||||
} else if(_f) {
|
|
||||||
fclose(_f);
|
|
||||||
_f = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VFSFileImpl::operator bool()
|
|
||||||
{
|
|
||||||
return (_isDirectory && _d != NULL) || _f != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t VFSFileImpl::getLastWrite() {
|
|
||||||
_getStat() ;
|
|
||||||
return _stat.st_mtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VFSFileImpl::_getStat() const
|
|
||||||
{
|
|
||||||
if(!_path) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
char * temp = (char *)malloc(strlen(_path)+strlen(_fs->_mountpoint)+1);
|
|
||||||
if(!temp) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sprintf(temp,"%s%s", _fs->_mountpoint, _path);
|
|
||||||
if(!stat(temp, &_stat)) {
|
|
||||||
_written = false;
|
|
||||||
}
|
|
||||||
free(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t VFSFileImpl::write(const uint8_t *buf, size_t size)
|
|
||||||
{
|
|
||||||
if(_isDirectory || !_f || !buf || !size) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
_written = true;
|
|
||||||
return fwrite(buf, 1, size, _f);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t VFSFileImpl::read(uint8_t* buf, size_t size)
|
|
||||||
{
|
|
||||||
if(_isDirectory || !_f || !buf || !size) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fread(buf, 1, size, _f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VFSFileImpl::flush()
|
|
||||||
{
|
|
||||||
if(_isDirectory || !_f) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fflush(_f);
|
|
||||||
// workaround for https://github.com/espressif/arduino-esp32/issues/1293
|
|
||||||
fsync(fileno(_f));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VFSFileImpl::seek(uint32_t pos, SeekMode mode)
|
|
||||||
{
|
|
||||||
if(_isDirectory || !_f) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
auto rc = fseek(_f, pos, mode);
|
|
||||||
return rc == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t VFSFileImpl::position() const
|
|
||||||
{
|
|
||||||
if(_isDirectory || !_f) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return ftell(_f);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t VFSFileImpl::size() const
|
|
||||||
{
|
|
||||||
if(_isDirectory || !_f) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (_written) {
|
|
||||||
_getStat();
|
|
||||||
}
|
|
||||||
return _stat.st_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* VFSFileImpl::name() const
|
|
||||||
{
|
|
||||||
return (const char*) _path;
|
|
||||||
}
|
|
||||||
|
|
||||||
//to implement
|
|
||||||
bool VFSFileImpl::isDirectory(void)
|
|
||||||
{
|
|
||||||
return _isDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
bool string_starts_with(std::string const &fullString, std::string const &begin) {
|
|
||||||
return fullString.rfind(begin, 0) == 0;
|
|
||||||
}
|
|
||||||
bool string_ends_with(std::string const &fullString, std::string const &ending) {
|
|
||||||
if (fullString.length() >= ending.length()) {
|
|
||||||
return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FileImplPtr VFSFileImpl::openNextFile(const char* mode)
|
|
||||||
{
|
|
||||||
if(!_isDirectory || !_d) {
|
|
||||||
return FileImplPtr();
|
|
||||||
}
|
|
||||||
struct dirent *file = readdir(_d);
|
|
||||||
if(file == NULL) {
|
|
||||||
return FileImplPtr();
|
|
||||||
}
|
|
||||||
if(file->d_type != DT_REG && file->d_type != DT_DIR) {
|
|
||||||
return openNextFile(mode);
|
|
||||||
}
|
|
||||||
std::string fname = std::string(file->d_name);
|
|
||||||
std::string name = std::string(_path);
|
|
||||||
if(!string_starts_with(fname, "/") && !string_ends_with(name, "/")) {
|
|
||||||
name += "/";
|
|
||||||
}
|
|
||||||
name += fname;
|
|
||||||
|
|
||||||
return std::make_shared<VFSFileImpl>(_fs, name.c_str(), mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VFSFileImpl::rewindDirectory(void)
|
|
||||||
{
|
|
||||||
if(!_isDirectory || !_d) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rewinddir(_d);
|
|
||||||
}
|
|
@ -1,77 +0,0 @@
|
|||||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#ifndef vfs_api_h
|
|
||||||
#define vfs_api_h
|
|
||||||
|
|
||||||
#include "FS.h"
|
|
||||||
#include "FSImpl.h"
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <sys/unistd.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace fs;
|
|
||||||
|
|
||||||
class VFSFileImpl;
|
|
||||||
|
|
||||||
class VFSImpl : public FSImpl
|
|
||||||
{
|
|
||||||
|
|
||||||
protected:
|
|
||||||
friend class VFSFileImpl;
|
|
||||||
|
|
||||||
public:
|
|
||||||
FileImplPtr open(const char* path, const char* mode) override;
|
|
||||||
bool exists(const char* path) override;
|
|
||||||
bool rename(const char* pathFrom, const char* pathTo) override;
|
|
||||||
bool remove(const char* path) override;
|
|
||||||
bool mkdir(const char *path) override;
|
|
||||||
bool rmdir(const char *path) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class VFSFileImpl : public FileImpl
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
VFSImpl* _fs;
|
|
||||||
FILE * _f;
|
|
||||||
DIR * _d;
|
|
||||||
char * _path;
|
|
||||||
bool _isDirectory;
|
|
||||||
mutable struct stat _stat;
|
|
||||||
mutable bool _written;
|
|
||||||
|
|
||||||
void _getStat() const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
VFSFileImpl(VFSImpl* fs, const char* path, const char* mode);
|
|
||||||
~VFSFileImpl() override;
|
|
||||||
size_t write(const uint8_t *buf, size_t size) override;
|
|
||||||
size_t read(uint8_t* buf, size_t size) override;
|
|
||||||
void flush() override;
|
|
||||||
bool seek(uint32_t pos, SeekMode mode) override;
|
|
||||||
size_t position() const override;
|
|
||||||
size_t size() const override;
|
|
||||||
void close() override;
|
|
||||||
const char* name() const override;
|
|
||||||
time_t getLastWrite() override;
|
|
||||||
bool isDirectory(void) override;
|
|
||||||
FileImplPtr openNextFile(const char* mode) override;
|
|
||||||
void rewindDirectory(void) override;
|
|
||||||
operator bool();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,181 +0,0 @@
|
|||||||
#include "FS.h"
|
|
||||||
#include "SPIFFS.h"
|
|
||||||
|
|
||||||
/* You only need to format SPIFFS the first time you run a
|
|
||||||
test or else use the SPIFFS plugin to create a partition
|
|
||||||
https://github.com/me-no-dev/arduino-esp32fs-plugin */
|
|
||||||
#define FORMAT_SPIFFS_IF_FAILED true
|
|
||||||
|
|
||||||
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
|
|
||||||
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.print(" DIR : ");
|
|
||||||
Serial.println(file.name());
|
|
||||||
if(levels){
|
|
||||||
listDir(fs, file.name(), levels -1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Serial.print(" FILE: ");
|
|
||||||
Serial.print(file.name());
|
|
||||||
Serial.print("\tSIZE: ");
|
|
||||||
Serial.println(file.size());
|
|
||||||
}
|
|
||||||
file = root.openNextFile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void readFile(fs::FS &fs, const char * path){
|
|
||||||
Serial.printf("Reading file: %s\r\n", path);
|
|
||||||
|
|
||||||
File file = fs.open(path);
|
|
||||||
if(!file || file.isDirectory()){
|
|
||||||
Serial.println("- failed to open file for reading");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Serial.println("- read from file:");
|
|
||||||
while(file.available()){
|
|
||||||
Serial.write(file.read());
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeFile(fs::FS &fs, const char * path, const char * message){
|
|
||||||
Serial.printf("Writing file: %s\r\n", path);
|
|
||||||
|
|
||||||
File file = fs.open(path, FILE_WRITE);
|
|
||||||
if(!file){
|
|
||||||
Serial.println("- failed to open file for writing");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(file.print(message)){
|
|
||||||
Serial.println("- file written");
|
|
||||||
} else {
|
|
||||||
Serial.println("- write failed");
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void appendFile(fs::FS &fs, const char * path, const char * message){
|
|
||||||
Serial.printf("Appending to file: %s\r\n", path);
|
|
||||||
|
|
||||||
File file = fs.open(path, FILE_APPEND);
|
|
||||||
if(!file){
|
|
||||||
Serial.println("- failed to open file for appending");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(file.print(message)){
|
|
||||||
Serial.println("- message appended");
|
|
||||||
} else {
|
|
||||||
Serial.println("- append failed");
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void renameFile(fs::FS &fs, const char * path1, const char * path2){
|
|
||||||
Serial.printf("Renaming file %s to %s\r\n", path1, path2);
|
|
||||||
if (fs.rename(path1, path2)) {
|
|
||||||
Serial.println("- file renamed");
|
|
||||||
} else {
|
|
||||||
Serial.println("- rename failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void deleteFile(fs::FS &fs, const char * path){
|
|
||||||
Serial.printf("Deleting file: %s\r\n", path);
|
|
||||||
if(fs.remove(path)){
|
|
||||||
Serial.println("- file deleted");
|
|
||||||
} else {
|
|
||||||
Serial.println("- delete failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void testFileIO(fs::FS &fs, const char * path){
|
|
||||||
Serial.printf("Testing file I/O with %s\r\n", path);
|
|
||||||
|
|
||||||
static uint8_t buf[512];
|
|
||||||
size_t len = 0;
|
|
||||||
File file = fs.open(path, FILE_WRITE);
|
|
||||||
if(!file){
|
|
||||||
Serial.println("- failed to open file for writing");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t i;
|
|
||||||
Serial.print("- writing" );
|
|
||||||
uint32_t start = millis();
|
|
||||||
for(i=0; i<2048; i++){
|
|
||||||
if ((i & 0x001F) == 0x001F){
|
|
||||||
Serial.print(".");
|
|
||||||
}
|
|
||||||
file.write(buf, 512);
|
|
||||||
}
|
|
||||||
Serial.println("");
|
|
||||||
uint32_t end = millis() - start;
|
|
||||||
Serial.printf(" - %u bytes written in %u ms\r\n", 2048 * 512, end);
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
file = fs.open(path);
|
|
||||||
start = millis();
|
|
||||||
end = start;
|
|
||||||
i = 0;
|
|
||||||
if(file && !file.isDirectory()){
|
|
||||||
len = file.size();
|
|
||||||
size_t flen = len;
|
|
||||||
start = millis();
|
|
||||||
Serial.print("- reading" );
|
|
||||||
while(len){
|
|
||||||
size_t toRead = len;
|
|
||||||
if(toRead > 512){
|
|
||||||
toRead = 512;
|
|
||||||
}
|
|
||||||
file.read(buf, toRead);
|
|
||||||
if ((i++ & 0x001F) == 0x001F){
|
|
||||||
Serial.print(".");
|
|
||||||
}
|
|
||||||
len -= toRead;
|
|
||||||
}
|
|
||||||
Serial.println("");
|
|
||||||
end = millis() - start;
|
|
||||||
Serial.printf("- %u bytes read in %u ms\r\n", flen, end);
|
|
||||||
file.close();
|
|
||||||
} else {
|
|
||||||
Serial.println("- failed to open file for reading");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup(){
|
|
||||||
Serial.begin(115200);
|
|
||||||
if(!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)){
|
|
||||||
Serial.println("SPIFFS Mount Failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
listDir(SPIFFS, "/", 0);
|
|
||||||
writeFile(SPIFFS, "/hello.txt", "Hello ");
|
|
||||||
appendFile(SPIFFS, "/hello.txt", "World!\r\n");
|
|
||||||
readFile(SPIFFS, "/hello.txt");
|
|
||||||
renameFile(SPIFFS, "/hello.txt", "/foo.txt");
|
|
||||||
readFile(SPIFFS, "/foo.txt");
|
|
||||||
deleteFile(SPIFFS, "/foo.txt");
|
|
||||||
testFileIO(SPIFFS, "/test.txt");
|
|
||||||
deleteFile(SPIFFS, "/test.txt");
|
|
||||||
Serial.println( "Test complete" );
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop(){
|
|
||||||
|
|
||||||
}
|
|
@ -1,177 +0,0 @@
|
|||||||
#include "FS.h"
|
|
||||||
#include "SPIFFS.h"
|
|
||||||
#include <time.h>
|
|
||||||
#include <WiFi.h>
|
|
||||||
|
|
||||||
const char* ssid = "your-ssid";
|
|
||||||
const char* password = "your-password";
|
|
||||||
|
|
||||||
long timezone = 1;
|
|
||||||
byte daysavetime = 1;
|
|
||||||
|
|
||||||
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
|
|
||||||
Serial.printf("Listing directory: %s\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.print(" DIR : ");
|
|
||||||
Serial.print (file.name());
|
|
||||||
time_t t= file.getLastWrite();
|
|
||||||
struct tm * tmstruct = localtime(&t);
|
|
||||||
Serial.printf(" LAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n",(tmstruct->tm_year)+1900,( tmstruct->tm_mon)+1, tmstruct->tm_mday,tmstruct->tm_hour , tmstruct->tm_min, tmstruct->tm_sec);
|
|
||||||
if(levels){
|
|
||||||
listDir(fs, file.name(), levels -1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Serial.print(" FILE: ");
|
|
||||||
Serial.print(file.name());
|
|
||||||
Serial.print(" SIZE: ");
|
|
||||||
Serial.print(file.size());
|
|
||||||
time_t t= file.getLastWrite();
|
|
||||||
struct tm * tmstruct = localtime(&t);
|
|
||||||
Serial.printf(" LAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n",(tmstruct->tm_year)+1900,( tmstruct->tm_mon)+1, tmstruct->tm_mday,tmstruct->tm_hour , tmstruct->tm_min, tmstruct->tm_sec);
|
|
||||||
}
|
|
||||||
file = root.openNextFile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void createDir(fs::FS &fs, const char * path){
|
|
||||||
Serial.printf("Creating Dir: %s\n", path);
|
|
||||||
if(fs.mkdir(path)){
|
|
||||||
Serial.println("Dir created");
|
|
||||||
} else {
|
|
||||||
Serial.println("mkdir failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void removeDir(fs::FS &fs, const char * path){
|
|
||||||
Serial.printf("Removing Dir: %s\n", path);
|
|
||||||
if(fs.rmdir(path)){
|
|
||||||
Serial.println("Dir removed");
|
|
||||||
} else {
|
|
||||||
Serial.println("rmdir failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void readFile(fs::FS &fs, const char * path){
|
|
||||||
Serial.printf("Reading file: %s\n", path);
|
|
||||||
|
|
||||||
File file = fs.open(path);
|
|
||||||
if(!file){
|
|
||||||
Serial.println("Failed to open file for reading");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Serial.print("Read from file: ");
|
|
||||||
while(file.available()){
|
|
||||||
Serial.write(file.read());
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeFile(fs::FS &fs, const char * path, const char * message){
|
|
||||||
Serial.printf("Writing file: %s\n", path);
|
|
||||||
|
|
||||||
File file = fs.open(path, FILE_WRITE);
|
|
||||||
if(!file){
|
|
||||||
Serial.println("Failed to open file for writing");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(file.print(message)){
|
|
||||||
Serial.println("File written");
|
|
||||||
} else {
|
|
||||||
Serial.println("Write failed");
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void appendFile(fs::FS &fs, const char * path, const char * message){
|
|
||||||
Serial.printf("Appending to file: %s\n", path);
|
|
||||||
|
|
||||||
File file = fs.open(path, FILE_APPEND);
|
|
||||||
if(!file){
|
|
||||||
Serial.println("Failed to open file for appending");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(file.print(message)){
|
|
||||||
Serial.println("Message appended");
|
|
||||||
} else {
|
|
||||||
Serial.println("Append failed");
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void renameFile(fs::FS &fs, const char * path1, const char * path2){
|
|
||||||
Serial.printf("Renaming file %s to %s\n", path1, path2);
|
|
||||||
if (fs.rename(path1, path2)) {
|
|
||||||
Serial.println("File renamed");
|
|
||||||
} else {
|
|
||||||
Serial.println("Rename failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void deleteFile(fs::FS &fs, const char * path){
|
|
||||||
Serial.printf("Deleting file: %s\n", path);
|
|
||||||
if(fs.remove(path)){
|
|
||||||
Serial.println("File deleted");
|
|
||||||
} else {
|
|
||||||
Serial.println("Delete failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup(){
|
|
||||||
Serial.begin(115200);
|
|
||||||
// We start by connecting to a WiFi network
|
|
||||||
Serial.println();
|
|
||||||
Serial.println();
|
|
||||||
Serial.print("Connecting to ");
|
|
||||||
Serial.println(ssid);
|
|
||||||
|
|
||||||
WiFi.begin(ssid, password);
|
|
||||||
|
|
||||||
while (WiFi.status() != WL_CONNECTED) {
|
|
||||||
delay(500);
|
|
||||||
Serial.print(".");
|
|
||||||
}
|
|
||||||
Serial.println("WiFi connected");
|
|
||||||
Serial.println("IP address: ");
|
|
||||||
Serial.println(WiFi.localIP());
|
|
||||||
Serial.println("Contacting Time Server");
|
|
||||||
configTime(3600*timezone, daysavetime*3600, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
|
|
||||||
struct tm tmstruct ;
|
|
||||||
delay(2000);
|
|
||||||
tmstruct.tm_year = 0;
|
|
||||||
getLocalTime(&tmstruct, 5000);
|
|
||||||
Serial.printf("\nNow is : %d-%02d-%02d %02d:%02d:%02d\n",(tmstruct.tm_year)+1900,( tmstruct.tm_mon)+1, tmstruct.tm_mday,tmstruct.tm_hour , tmstruct.tm_min, tmstruct.tm_sec);
|
|
||||||
Serial.println("");
|
|
||||||
|
|
||||||
if(!SPIFFS.begin()){
|
|
||||||
Serial.println("Card Mount Failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
listDir(SPIFFS, "/", 0);
|
|
||||||
removeDir(SPIFFS, "/mydir");
|
|
||||||
createDir(SPIFFS, "/mydir");
|
|
||||||
deleteFile(SPIFFS, "/hello.txt");
|
|
||||||
writeFile(SPIFFS, "/hello.txt", "Hello ");
|
|
||||||
appendFile(SPIFFS, "/hello.txt", "World!\n");
|
|
||||||
listDir(SPIFFS, "/", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop(){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
|||||||
name=SPIFFS
|
|
||||||
version=1.0
|
|
||||||
author=Hristo Gochkov, Ivan Grokhtkov
|
|
||||||
maintainer=Hristo Gochkov <hristo@espressif.com>
|
|
||||||
sentence=ESP32 SPIFFS File System
|
|
||||||
paragraph=
|
|
||||||
category=Data Storage
|
|
||||||
url=
|
|
||||||
architectures=esp32
|
|
@ -1,142 +0,0 @@
|
|||||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include "vfs_api.h"
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <sys/unistd.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include "esp_spiffs.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "SPIFFS.h"
|
|
||||||
|
|
||||||
#include "esp32-hal-log.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
using namespace fs;
|
|
||||||
|
|
||||||
class SPIFFSImpl : public VFSImpl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SPIFFSImpl();
|
|
||||||
virtual ~SPIFFSImpl() { }
|
|
||||||
virtual bool exists(const char* path);
|
|
||||||
};
|
|
||||||
|
|
||||||
SPIFFSImpl::SPIFFSImpl()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SPIFFSImpl::exists(const char* path)
|
|
||||||
{
|
|
||||||
File f = open(path, "r");
|
|
||||||
return (f == true) && !f.isDirectory();
|
|
||||||
}
|
|
||||||
|
|
||||||
SPIFFSFS::SPIFFSFS() : FS(FSImplPtr(new SPIFFSImpl())), partitionLabel_(NULL)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
SPIFFSFS::~SPIFFSFS()
|
|
||||||
{
|
|
||||||
if (partitionLabel_){
|
|
||||||
free(partitionLabel_);
|
|
||||||
partitionLabel_ = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SPIFFSFS::begin(bool formatOnFail, const char * basePath, uint8_t maxOpenFiles, const char * partitionLabel)
|
|
||||||
{
|
|
||||||
if (partitionLabel_){
|
|
||||||
free(partitionLabel_);
|
|
||||||
partitionLabel_ = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (partitionLabel){
|
|
||||||
partitionLabel_ = strdup(partitionLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(esp_spiffs_mounted(partitionLabel_)){
|
|
||||||
log_w("SPIFFS Already Mounted!");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_vfs_spiffs_conf_t conf = {
|
|
||||||
.base_path = basePath,
|
|
||||||
.partition_label = partitionLabel_,
|
|
||||||
.max_files = maxOpenFiles,
|
|
||||||
.format_if_mount_failed = false
|
|
||||||
};
|
|
||||||
|
|
||||||
esp_err_t err = esp_vfs_spiffs_register(&conf);
|
|
||||||
if(err == ESP_FAIL && formatOnFail){
|
|
||||||
if(format()){
|
|
||||||
err = esp_vfs_spiffs_register(&conf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(err != ESP_OK){
|
|
||||||
log_e("Mounting SPIFFS failed! Error: %d", err);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
_impl->mountpoint(basePath);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SPIFFSFS::end()
|
|
||||||
{
|
|
||||||
if(esp_spiffs_mounted(partitionLabel_)){
|
|
||||||
esp_err_t err = esp_vfs_spiffs_unregister(partitionLabel_);
|
|
||||||
if(err){
|
|
||||||
log_e("Unmounting SPIFFS failed! Error: %d", err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_impl->mountpoint(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SPIFFSFS::format()
|
|
||||||
{
|
|
||||||
esp_err_t err = esp_spiffs_format(partitionLabel_);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
log_e("Formatting SPIFFS failed! Error: %d", err);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t SPIFFSFS::totalBytes()
|
|
||||||
{
|
|
||||||
size_t total,used;
|
|
||||||
if(esp_spiffs_info(partitionLabel_, &total, &used)){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t SPIFFSFS::usedBytes()
|
|
||||||
{
|
|
||||||
size_t total,used;
|
|
||||||
if(esp_spiffs_info(partitionLabel_, &total, &used)){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return used;
|
|
||||||
}
|
|
||||||
|
|
||||||
SPIFFSFS SPIFFS;
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
|||||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
#ifndef _SPIFFS_H_
|
|
||||||
#define _SPIFFS_H_
|
|
||||||
|
|
||||||
#include "FS.h"
|
|
||||||
|
|
||||||
namespace fs
|
|
||||||
{
|
|
||||||
|
|
||||||
class SPIFFSFS : public FS
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SPIFFSFS();
|
|
||||||
~SPIFFSFS();
|
|
||||||
bool begin(bool formatOnFail=false, const char * basePath="/spiffs", uint8_t maxOpenFiles=10, const char * partitionLabel=NULL);
|
|
||||||
bool format();
|
|
||||||
size_t totalBytes();
|
|
||||||
size_t usedBytes();
|
|
||||||
void end();
|
|
||||||
|
|
||||||
private:
|
|
||||||
char * partitionLabel_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extern fs::SPIFFSFS SPIFFS;
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
Reference in New Issue
Block a user