From 04bb28bc20305661fd0ecf9ac8822b7a3224cc66 Mon Sep 17 00:00:00 2001 From: gemu Date: Sat, 27 Jan 2024 09:06:41 +0100 Subject: [PATCH] fix email32 file system (#20603) * fix file system * fix email attachments * Update MB_FS.h --- .../ESP-Mail-Client/src/extras/MB_FS.h | 962 ++------------ .../ESP-Mail-Client/src/extras/MB_FS_org.h | 1139 +++++++++++++++++ .../xdrv_01_2_webserver_esp32_mail.ino | 2 + 3 files changed, 1230 insertions(+), 873 deletions(-) create mode 100644 lib/libesp32/ESP-Mail-Client/src/extras/MB_FS_org.h diff --git a/lib/libesp32/ESP-Mail-Client/src/extras/MB_FS.h b/lib/libesp32/ESP-Mail-Client/src/extras/MB_FS.h index 96740627b..caed959a9 100644 --- a/lib/libesp32/ESP-Mail-Client/src/extras/MB_FS.h +++ b/lib/libesp32/ESP-Mail-Client/src/extras/MB_FS.h @@ -31,43 +31,10 @@ #define MBFS_CLASS_H #include -#include "MB_MCU.h" - -#define FS_NO_GLOBALS -#if defined(ESP32) || defined(ESP8266) || defined(MB_ARDUINO_PICO) -#if defined(MBFS_FLASH_FS) || defined(MBFS_SD_FS) #include -#endif -#endif #include "MB_FS_Interfaces.h" #include MB_STRING_INCLUDE_CLASS -#if defined(MBFS_FLASH_FS) || defined(MBFS_SD_FS) -#include "SPI.h" -#endif - -#if defined(ESP32) && __has_include() -#ifdef _LITTLEFS_H_ -#define MB_FS_USE_POSIX_STAT -#include -namespace mb_fs_ns -{ - inline bool exists(const char *mountPoint, const char *filename) - { - MB_String path = mountPoint; - path += filename; - struct stat st; - return stat(path.c_str(), &st) == 0; - } -}; -#endif -#endif - -using namespace mb_string; - -#if defined(BOARD_HAS_PSRAM) && defined(MB_STRING_USE_PSRAM) -#include -#endif #define MB_FS_ERROR_FILE_IO_ERROR -300 #define MB_FS_ERROR_FILE_NOT_FOUND -301 @@ -75,6 +42,14 @@ using namespace mb_string; #define MB_FS_ERROR_SD_STORAGE_IS_NOT_READY -303 #define MB_FS_ERROR_FILE_STILL_OPENED -304 + +#define mbfs_file_type mb_fs_mem_storage_type +#define mbfs_flash mb_fs_mem_storage_type_flash +#define mbfs_sd mb_fs_mem_storage_type_sd +#define mbfs_undefined mb_fs_mem_storage_type_undefined + +#define mbfs_type (mbfs_file_type) + typedef enum { mb_fs_mem_storage_type_undefined, @@ -90,733 +65,158 @@ typedef enum mb_fs_open_mode_append } mb_fs_open_mode; -#define mbfs_file_type mb_fs_mem_storage_type -#define mbfs_flash mb_fs_mem_storage_type_flash -#define mbfs_sd mb_fs_mem_storage_type_sd -#define mbfs_undefined mb_fs_mem_storage_type_undefined +extern FS *ufsp; -#define mbfs_type (mbfs_file_type) - -#if defined(ARDUINO_ARCH_SAMD) || defined(__AVR_ATmega4809__) || defined(ARDUINO_NANO_RP2040_CONNECT) -#if !defined(MBFS_SDFAT_ENABLED) -struct mbfs_sd_config_info_t -{ - int ss = -1; -}; -#endif -#elif defined(ESP32) || defined(MBFS_SDFAT_ENABLED) - -#if defined(ESP32) -struct mbfs_sd_mmc_config_info_t -{ - const char *mountpoint = ""; - bool mode1bit = false; - bool format_if_mount_failed = false; -}; -#endif - -struct mbfs_sd_config_info_t -{ - int ss = -1; - int sck = -1; - int miso = -1; - int mosi = -1; - uint32_t frequency = 4000000; - -#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) - - SdSpiConfig *sdFatSPIConfig = nullptr; - SdioConfig *sdFatSDIOConfig = nullptr; - -#endif - -#if defined(ESP32) - -#if defined(MBFS_SD_FS) - SPIClass *spiConfig = nullptr; -#endif - mbfs_sd_mmc_config_info_t sdMMCConfig; -#endif - -#if defined(MBFS_SDFAT_ENABLED) - SPIClass *spiConfig = nullptr; -#endif -}; - -#elif defined(ESP8266) || defined(MB_ARDUINO_PICO) -struct mbfs_sd_config_info_t -{ - int ss = -1; -#if defined(MBFS_SD_FS) - SDFSConfig *sdFSConfig = nullptr; -#endif -}; -#else -struct mbfs_sd_config_info_t -{ - int ss = -1; -}; -#endif - -class MB_FS -{ +class MB_FS { public: MB_FS() {} ~MB_FS() {} - struct mbfs_sd_config_info_t sd_config; - // Assign the SD card interfaces with GPIO pins. - bool sdBegin(int ss = -1, int sck = -1, int miso = -1, int mosi = -1, uint32_t frequency = 4000000) - { - if (sd_rdy) - return true; - -#if defined(MBFS_SD_FS) && defined(MBFS_CARD_TYPE_SD) - sd_config.ss = ss; -#if defined(ESP32) - sd_config.sck = sck; - sd_config.miso = miso; - sd_config.mosi = mosi; - SPI.begin(sck, miso, mosi, ss); - sd_config.frequency = frequency; - return sdSPIBegin(ss, &SPI, frequency); -#elif defined(ESP8266) || defined(ARDUINO_ARCH_SAMD) || defined(__AVR_ATmega4809__) || defined(ARDUINO_NANO_RP2040_CONNECT) - sd_rdy = MBFS_SD_FS.begin(ss); - return sd_rdy; -#elif defined(MB_ARDUINO_PICO) - SDFSConfig c; - c.setCSPin(ss); - c.setSPISpeed(frequency); - MBFS_SD_FS.setConfig(c); - sd_rdy = MBFS_SD_FS.begin(); - return sd_rdy; -#endif - -#endif - return false; + bool sdBegin(int ss = -1, int sck = -1, int miso = -1, int mosi = -1, uint32_t frequency = 4000000) { + mfsp = ufsp; + return true; } -#if defined(ESP32) && defined(MBFS_SD_FS) && defined(MBFS_CARD_TYPE_SD) - - // Assign the SD card interfaces with SPIClass object pointer (ESP32 only). - bool sdSPIBegin(int ss, SPIClass *spiConfig, uint32_t frequency) - { - - if (sd_rdy) - return true; - - sd_config.frequency = frequency; - -#if defined(ESP32) - - sd_config.ss = ss; - - if (spiConfig) - sd_config.spiConfig = spiConfig; - else - sd_config.spiConfig = &SPI; - -#if !defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) - if (ss > -1) - sd_rdy = MBFS_SD_FS.begin(ss, *sd_config.spiConfig, frequency); - else - sd_rdy = MBFS_SD_FS.begin(); -#endif - -#elif defined(ESP8266) || defined(MB_ARDUINO_PICO) - - cfg->_int.sd_config.sck = sck; - - if (ss > -1) - sd_rdy = MBFS_SD_FS.begin(ss); - else - sd_rdy = MBFS_SD_FS.begin(SD_CS_PIN); -#endif - - return sd_rdy; - } - -#endif - -#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) - - // Assign the SD card interfaces with SdSpiConfig object pointer and SPI pins assignment. - bool sdFatBegin(SdSpiConfig *sdFatSPIConfig, int ss, int sck, int miso, int mosi) - { - - if (sd_rdy) - return true; - - if (sdFatSPIConfig) - { - sd_config.sdFatSPIConfig = sdFatSPIConfig; - sd_config.spiConfig = &SPI; - sd_config.ss = ss; - -#if defined(ESP32) - if (ss > -1) - sd_config.spiConfig->begin(sck, miso, mosi, ss); -#endif - - sd_rdy = MBFS_SD_FS.begin(*sd_config.sdFatSPIConfig); - return sd_rdy; - } - - return false; - } - - // Assign the SD card interfaces with SdioConfig object pointer. - bool sdFatBegin(SdioConfig *sdFatSDIOConfig) - { - - if (sd_rdy) - return true; - -#if defined(HAS_SDIO_CLASS) // Default is 0 (no SDIO) in SdFatConfig.h - -#if HAS_SDIO_CLASS - - if (sdFatSDIOConfig) - { - sd_config.sdFatSDIOConfig = sdFatSDIOConfig; - - sd_rdy = MBFS_SD_FS.begin(*sd_config.sdFatSDIOConfig); - return sd_rdy; - } -#endif - -#endif - - return false; - } -#endif - -#if (defined(ESP8266) || defined(MB_ARDUINO_PICO)) && defined(MBFS_SD_FS) - // Assign the SD card interfaces with SDFSConfig object pointer (ESP8266 and Pico only). - bool sdFatBegin(SDFSConfig *sdFSConfig) - { - - if (sd_rdy) - return true; - - if (sdFSConfig) - { - sd_config.sdFSConfig = sdFSConfig; - SDFS.setConfig(*sd_config.sdFSConfig); - sd_rdy = SDFS.begin(); - return sd_rdy; - } - - return false; - } -#endif - - // Assign the SD_MMC card interfaces (ESP32 only). - bool sdMMCBegin(const char *mountpoint, bool mode1bit, bool format_if_mount_failed) - { - - if (sd_rdy) - return true; - -#if defined(ESP32) -#if defined(MBFS_CARD_TYPE_SD_MMC) - - sd_config.sdMMCConfig.mountpoint = mountpoint; - sd_config.sdMMCConfig.mode1bit = mode1bit; - sd_config.sdMMCConfig.format_if_mount_failed = format_if_mount_failed; - - sd_rdy = MBFS_SD_FS.begin(mountpoint, mode1bit, format_if_mount_failed); - return sd_rdy; -#endif -#endif - return false; + bool sdSPIBegin(int ss, SPIClass *spiConfig, uint32_t frequency) { + mfsp = ufsp; + return true; } // Check the mounting status of Flash storage. - bool flashReady() - { -#if defined MBFS_FLASH_FS - - if (flash_rdy) - return true; - -#if defined(ESP32) - -#if defined(MBFS_FORMAT_FLASH) - flash_rdy = MBFS_FLASH_FS.begin(true); -#else - flash_rdy = MBFS_FLASH_FS.begin(); -#endif - -#elif defined(ESP8266) || defined(MB_ARDUINO_PICO) - flash_rdy = MBFS_FLASH_FS.begin(); -#endif - -#endif - - return flash_rdy; + bool flashReady() { + return true; } // Check the mounting status of SD storage. - bool sdReady() - { - -#if defined(MBFS_SD_FS) - - if (sd_rdy) - return true; - -#if defined(ESP32) - -#if defined(MBFS_CARD_TYPE_SD) - - if (!sd_config.spiConfig) - { - if (sd_config.ss > -1) - SPI.begin(sd_config.sck, sd_config.miso, sd_config.mosi, sd_config.ss); - sd_config.spiConfig = &SPI; - } - -#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) - - if (!sd_rdy) - { - if (sd_config.sdFatSPIConfig) - sd_rdy = MBFS_SD_FS.begin(*sd_config.sdFatSPIConfig); - else if (sd_config.sdFatSDIOConfig) - sd_rdy = MBFS_SD_FS.begin(*sd_config.sdFatSDIOConfig); - } - -#else - if (!sd_rdy) - sd_rdy = sdSPIBegin(sd_config.ss, sd_config.spiConfig, sd_config.frequency); - -#endif - -#elif defined(MBFS_CARD_TYPE_SD_MMC) - if (!sd_rdy) - sd_rdy = sdMMCBegin(sd_config.sdMMCConfig.mountpoint, sd_config.sdMMCConfig.mode1bit, sd_config.sdMMCConfig.format_if_mount_failed); -#endif - -#elif defined(ESP8266) || defined(MB_ARDUINO_PICO) - if (!sd_rdy) - { - if (sd_config.sdFSConfig) - sd_rdy = sdFatBegin(sd_config.sdFSConfig); - else - sd_rdy = sdBegin(sd_config.ss); - } - -#elif defined(ARDUINO_ARCH_SAMD) || defined(__AVR_ATmega4809__) || defined(ARDUINO_NANO_RP2040_CONNECT) - if (!sd_rdy) - sd_rdy = sdBegin(sd_config.ss); -#endif - -#endif - - return sd_rdy; + bool sdReady() { + return true; } // Check the mounting status of Flash or SD storage with mb_fs_mem_storage_type. - bool checkStorageReady(mbfs_file_type type) - { - -#if defined(MBFS_USE_FILE_STORAGE) - if (type == mbfs_flash) - { - if (!flash_rdy) - flashReady(); - return flash_rdy; - } - else if (type == mbfs_sd) - { - if (!sd_rdy) - sdReady(); - return sd_rdy; - } -#endif - - return false; + bool checkStorageReady(mbfs_file_type type) { + return true; } - // Open file for read or write with file name, mb_fs_mem_storage_type and mb_fs_open_mode. - // return size of file (read) or 0 (write) or negative value for error - int open(const MB_String &filename, mbfs_file_type type, mb_fs_open_mode mode) - { - -#if defined(MBFS_USE_FILE_STORAGE) - - if (!checkStorageReady(type)) - { - if (type == mbfs_flash) - return MB_FS_ERROR_FLASH_STORAGE_IS_NOT_READY; - else if (type == mbfs_sd) - return MB_FS_ERROR_SD_STORAGE_IS_NOT_READY; - else - return MB_FS_ERROR_FILE_IO_ERROR; + int open(const MB_String &filename, mbfs_file_type type, mb_fs_open_mode mode) { + char fmode[8]; + switch (mode) { + case mb_fs_open_mode_read: + strcpy(fmode, "r"); + break; + case mb_fs_open_mode_write: + strcpy(fmode, "w"); + break; + case mb_fs_open_mode_append: + strcpy(fmode, "a"); + break; } - - if (mode == mb_fs_open_mode_read) - { - if (!existed(filename.c_str(), type)) - return MB_FS_ERROR_FILE_NOT_FOUND; - } - - int ret = openFile(filename, type, mode); - - if (ret < 0) - return ret; - - if (ready(type)) - return ret; - -#endif - return MB_FS_ERROR_FILE_IO_ERROR; + flash_file = filename; + mfsp = ufsp; + mb_File = mfsp->open(filename.c_str(), fmode); + //Serial.printf(">>> 1 %s, %s, %d ", filename.c_str(), fmode, mb_File); + return mb_File; } - // Check if file is already open. - bool ready(mbfs_file_type type) - { -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - return true; -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && mb_sdFs) - return true; -#endif - return false; + bool ready(mbfs_file_type type) { + return true; } - // Get file for read/write with file name, mb_fs_mem_storage_type and mb_fs_open_mode. - int size(mbfs_file_type type) - { - int size = 0; - -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - size = mb_flashFs.size(); -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && mb_sdFs) - size = mb_sdFs.size(); -#endif - return size; + int size(mbfs_file_type type) { + return mb_File.size(); } // Check if file is ready to read/write. - int available(mbfs_file_type type) - { - int available = 0; - -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - available = mb_flashFs.available(); -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && mb_sdFs) - available = mb_sdFs.available(); -#endif - return available; + int available(mbfs_file_type type) { + return mb_File.available(); } // Read byte array. Return the number of bytes that completed read or negative value for error. - int read(mbfs_file_type type, uint8_t *buf, size_t len) - { - int read = 0; -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - read = mb_flashFs.read(buf, len); -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && mb_sdFs) - read = mb_sdFs.read(buf, len); -#endif - return read; + int read(mbfs_file_type type, uint8_t *buf, size_t len) { + return mb_File.read(buf, len); } // Print char array. Return the number of bytes that completed write or negative value for error. - int print(mbfs_file_type type, const char *str) - { - int write = 0; -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - write = mb_flashFs.print(str); -#endif -#if defined(MBFS_SD_FS) - - if (type == mbfs_sd && mb_sdFs) - write = mb_sdFs.print(str); -#endif - return write; + int print(mbfs_file_type type, const char *str) { + return mb_File.print(str); } // Print char array with new line. Return the number of bytes that completed write or negative value for error. - int println(mbfs_file_type type, const char *str) - { - int write = print(type, str); - if (write == (int)strlen(str)) - write += print(type, (const char *)MBSTRING_FLASH_MCR("\n")); - return write; + int println(mbfs_file_type type, const char *str) { + return mb_File.print(str); } // Print integer. Return the number of bytes that completed write or negative value for error. - int print(mbfs_file_type type, int v) - { - int write = 0; -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - write = mb_flashFs.print(v); -#endif -#if defined(MBFS_SD_FS) - - if (type == mbfs_sd && mb_sdFs) - write = mb_sdFs.print(v); -#endif - return write; + int print(mbfs_file_type type, int v) { + return mb_File.print(v); } // Print integer with newline. Return the number of bytes that completed write or negative value for error. - int println(mbfs_file_type type, int v) - { - int write = print(type, v); - if (write > 0) - write += print(type, (const char *)MBSTRING_FLASH_MCR("\n")); - return write; + int println(mbfs_file_type type, int v) { + return mb_File.print(v); } - int print(mbfs_file_type type, unsigned int v) - { - int write = 0; -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - write = mb_flashFs.print(v); -#endif -#if defined(MBFS_SD_FS) - - if (type == mbfs_sd && mb_sdFs) - write = mb_sdFs.print(v); -#endif - return write; + int print(mbfs_file_type type, unsigned int v) { + return mb_File.print(v); } // Print integer with newline. Return the number of bytes that completed write or negative value for error. - int println(mbfs_file_type type, unsigned int v) - { - int write = print(type, v); - if (write > 0) - write += print(type, (const char *)MBSTRING_FLASH_MCR("\n")); - return write; + int println(mbfs_file_type type, unsigned int v) { + return mb_File.print(v); } // Write byte array. Return the number of bytes that completed write or negative value for error. - int write(mbfs_file_type type, uint8_t *buf, size_t len) - { - int write = 0; -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - write = mb_flashFs.write(buf, len); -#endif -#if defined(MBFS_SD_FS) - - if (type == mbfs_sd && mb_sdFs) - write = mb_sdFs.write(buf, len); -#endif - return write; + int write(mbfs_file_type type, uint8_t *buf, size_t len) { + return mb_File.write(buf, len); } // Close file. - void close(mbfs_file_type type) - { - -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs && flash_opened) - { - mb_flashFs.close(); - flash_filename_crc = 0; - flash_opened = false; - flash_open_mode = mb_fs_open_mode_undefined; - } -#endif - -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && mb_sdFs && sd_opened) - { - mb_sdFs.close(); - sd_filename_crc = 0; - sd_opened = false; - sd_open_mode = mb_fs_open_mode_undefined; - } -#endif + void close(mbfs_file_type type) { + mb_File.close(); } // Check file existence. - bool existed(const MB_String &filename, mbfs_file_type type) - { - - if (!checkStorageReady(type)) - return false; - -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash) - { - -// The workaround for ESP32 LittleFS when calling vfs_api.cpp open() issue. -// See https://github.com/espressif/arduino-esp32/issues/7615 -#if defined(MB_FS_USE_POSIX_STAT) - return mb_fs_ns::exists("/littlefs", filename.c_str()); -#else - return MBFS_FLASH_FS.exists(filename.c_str()); -#endif - } - -#endif - -#if defined(MBFS_SD_FS) - if (type == mbfs_sd) - { -#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) - MBFS_SD_FILE file; - bool ret = file.open(filename.c_str(), O_RDONLY); - file.close(); - return ret; -#else - return MBFS_SD_FS.exists(filename.c_str()); -#endif - } -#endif - - return false; + bool existed(const MB_String &filename, mbfs_file_type type) { + return mfsp->exists(filename.c_str()); } // Seek to position in file. - bool seek(mbfs_file_type type, int pos) - { - -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - return mb_flashFs.seek(pos); -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && mb_sdFs) - return mb_sdFs.seek(pos); -#endif - - return false; + bool seek(mbfs_file_type type, int pos) { + return mb_File.seek(pos); } // Read byte. Return the 1 for completed read or negative value for error. - int read(mbfs_file_type type) - { -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - return mb_flashFs.read(); -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && mb_sdFs) - return mb_sdFs.read(); -#endif - return -1; + int read(mbfs_file_type type) { + return mb_File.read(); } // Write byte. Return the 1 for completed write or negative value for error. - int write(mbfs_file_type type, uint8_t v) - { -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - return mb_flashFs.write(v); -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && mb_sdFs) - return mb_sdFs.write(v); -#endif - return -1; + int write(mbfs_file_type type, uint8_t v) { + return mb_File.write(v); } - bool remove(const MB_String &filename, mbfs_file_type type) - { - if (!checkStorageReady(type)) - return false; - -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && !flashReady()) - return false; -#endif - -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && !sdReady()) - return false; -#endif - - if (!existed(filename, type)) - return true; - -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash) - return MBFS_FLASH_FS.remove(filename.c_str()); -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd) - { -#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) - if (mb_sdFs.open(filename.c_str(), O_RDWR | O_CREAT | O_APPEND)) - { - mb_sdFs.remove(); - mb_sdFs.close(); - return true; - } -#else - return MBFS_SD_FS.remove(filename.c_str()); -#endif - } - -#endif - return false; + bool remove(const MB_String &filename, mbfs_file_type type) { + return mfsp->remove(filename.c_str()); } -// Get the Flash file instance. -#if defined(MBFS_FLASH_FS) - fs::File &getFlashFile() - { - return mb_flashFs; + fs::File &getFlashFile() { + return mb_File; } -#endif - -// Get the SD file instance. -#if defined(MBFS_SD_FS) - MBFS_SD_FILE &getSDFile() - { - return mb_sdFs; - } -#endif // Get name of opened file. - const char *name(mbfs_file_type type) - { -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - return flash_file.c_str(); -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && mb_sdFs) - return sd_file.c_str(); -#endif - - return ""; + const char *name(mbfs_file_type type) { + return flash_file.c_str(); } // Calculate CRC16 of byte array. - uint16_t calCRC(const char *buf) - { + uint16_t calCRC(const char *buf) { uint8_t x; uint16_t crc = 0xFFFF; int length = (int)strlen(buf); - while (length--) - { + while (length--) { x = crc >> 8 ^ *buf++; x ^= x >> 4; crc = (crc << 8) ^ ((uint16_t)(x << 12)) ^ ((uint16_t)(x << 5)) ^ ((uint16_t)x); @@ -825,19 +225,16 @@ public: } // Free reserved memory at pointer. - void delP(void *ptr) - { + void delP(void *ptr) { void **p = (void **)ptr; - if (*p) - { + if (*p) { free(*p); *p = 0; } } // Allocate memory - void *newP(size_t len, bool clear = true) - { + void *newP(size_t len, bool clear = true) { void *p; size_t newLen = getReservedLen(len); #if defined(BOARD_HAS_PSRAM) && defined(MB_STRING_USE_PSRAM) @@ -872,8 +269,7 @@ public: return p; } - size_t getReservedLen(size_t len) - { + size_t getReservedLen(size_t len) { int blen = len + 1; int newlen = (blen / 4) * 4; @@ -884,20 +280,17 @@ public: return (size_t)newlen; } - void createDirs(MB_String dirs, mbfs_file_type type) - { + void createDirs(MB_String dirs, mbfs_file_type type) { if (!longNameSupported()) return; MB_String dir; int count = 0; int lastPos = 0; - for (size_t i = 0; i < dirs.length(); i++) - { + for (size_t i = 0; i < dirs.length(); i++) { dir.append(1, dirs[i]); count++; - if (dirs[i] == '/' && i > 0) - { + if (dirs[i] == '/' && i > 0) { if (dir.length() > 0) { @@ -936,8 +329,7 @@ public: dir.clear(); } - bool longNameSupported() - { + bool longNameSupported() { #if defined(MBFS_SDFAT_ENABLED) || defined(MBFS_FLASH_FS) return true; @@ -952,186 +344,10 @@ public: private: uint16_t flash_filename_crc = 0; - uint16_t sd_filename_crc = 0; MB_String flash_file, sd_file; - mb_fs_open_mode flash_open_mode = mb_fs_open_mode_undefined; - mb_fs_open_mode sd_open_mode = mb_fs_open_mode_undefined; - bool flash_opened = false; - bool sd_opened = false; - bool sd_rdy = false; - bool flash_rdy = false; - uint16_t loopCount = 0; + FS *mfsp; + File mb_File; -#if defined(MBFS_FLASH_FS) - fs::File mb_flashFs; -#endif -#if defined(MBFS_SD_FS) - MBFS_SD_FILE mb_sdFs; -#endif - - int openFile(const MB_String &filename, mb_fs_mem_storage_type type, mb_fs_open_mode mode) - { - -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash) - return openFlashFile(filename, mode); -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd) - return openSDFile(filename, mode); -#endif - return MB_FS_ERROR_FILE_IO_ERROR; - } - - int openSDFile(const MB_String &filename, mb_fs_open_mode mode) - { - int ret = MB_FS_ERROR_FILE_IO_ERROR; - -#if defined(MBFS_SD_FS) - - if (mode == mb_fs_open_mode_read || mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) - { - uint16_t crc = calCRC(filename.c_str()); - - if (mode == sd_open_mode && flash_filename_crc == crc && sd_opened) // same sd file opened, leave it - return MB_FS_ERROR_FILE_STILL_OPENED; - - if (sd_opened) - close(mbfs_sd); // sd file opened, close it - - flash_filename_crc = crc; - } - -#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) - - if (mode == mb_fs_open_mode_read) - { - if (mb_sdFs.open(filename.c_str(), O_RDONLY)) - { - sd_file = filename; - sd_opened = true; - sd_open_mode = mode; - ret = mb_sdFs.size(); - } - } - else if (mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) - { - if (mode == mb_fs_open_mode_write) - remove(filename, mb_fs_mem_storage_type_sd); - - createDirs(filename, mb_fs_mem_storage_type_sd); - if (mb_sdFs.open(filename.c_str(), O_RDWR | O_CREAT | O_APPEND)) - { - sd_file = filename; - sd_opened = true; - sd_open_mode = mode; - ret = 0; - } - } - -#else - - if (mode == mb_fs_open_mode_read) - { -#if defined(ESP32) || defined(ESP8266) - mb_sdFs = MBFS_SD_FS.open(filename.c_str(), FILE_READ); -#else - mb_sdFs = MBFS_SD_FS.open(filename.c_str(), "r"); -#endif - if (mb_sdFs) - { - sd_file = filename; - sd_opened = true; - sd_open_mode = mode; - ret = mb_sdFs.size(); - } - } - else if (mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) - { - if (mode == mb_fs_open_mode_write) - remove(filename, mb_fs_mem_storage_type_sd); - - createDirs(filename, mb_fs_mem_storage_type_sd); -#if defined(ESP32) - if (mode == mb_fs_open_mode_write) - mb_sdFs = MBFS_SD_FS.open(filename.c_str(), FILE_WRITE); - else - mb_sdFs = MBFS_SD_FS.open(filename.c_str(), FILE_APPEND); -#elif defined(ESP8266) - mb_sdFs = MBFS_SD_FS.open(filename.c_str(), FILE_WRITE); -#else - if (mode == mb_fs_open_mode_write) - mb_sdFs = MBFS_SD_FS.open(filename.c_str(), "w"); - else - mb_sdFs = MBFS_SD_FS.open(filename.c_str(), "a"); -#endif - - if (mb_sdFs) - { - sd_file = filename; - sd_opened = true; - sd_open_mode = mode; - ret = 0; - } - } -#endif - -#endif - return ret; - } - - int openFlashFile(const MB_String &filename, mb_fs_open_mode mode) - { - int ret = MB_FS_ERROR_FILE_IO_ERROR; - -#if defined(MBFS_FLASH_FS) - - if (mode == mb_fs_open_mode_read || mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) - { - uint16_t crc = calCRC(filename.c_str()); - if (mode == flash_open_mode && sd_filename_crc == crc && flash_opened) // same flash file opened, leave it - return MB_FS_ERROR_FILE_STILL_OPENED; - - if (flash_opened) - close(mbfs_flash); // flash file opened, close it - - sd_filename_crc = crc; - } - - if (mode == mb_fs_open_mode_read) - { - mb_flashFs = MBFS_FLASH_FS.open(filename.c_str(), "r"); - if (mb_flashFs) - { - flash_file = filename; - flash_opened = true; - flash_open_mode = mode; - ret = mb_flashFs.size(); - } - } - else if (mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) - { - if (mode == mb_fs_open_mode_write) - remove(filename, mb_fs_mem_storage_type_flash); - - createDirs(filename, mb_fs_mem_storage_type_flash); - if (mode == mb_fs_open_mode_write) - mb_flashFs = MBFS_FLASH_FS.open(filename.c_str(), "w"); - else - mb_flashFs = MBFS_FLASH_FS.open(filename.c_str(), "a"); - - if (mb_flashFs) - { - flash_file = filename; - flash_opened = true; - flash_open_mode = mode; - ret = 0; - } - } - -#endif - return ret; - } }; #endif diff --git a/lib/libesp32/ESP-Mail-Client/src/extras/MB_FS_org.h b/lib/libesp32/ESP-Mail-Client/src/extras/MB_FS_org.h new file mode 100644 index 000000000..682a3d78e --- /dev/null +++ b/lib/libesp32/ESP-Mail-Client/src/extras/MB_FS_org.h @@ -0,0 +1,1139 @@ +/** + * The MB_FS, filesystems wrapper class v1.0.16 + * + * This wrapper class is for SD and Flash filesystems interface which supports SdFat (//https://github.com/greiman/SdFat) + * + * Created June 14, 2023 + * + * The MIT License (MIT) + * Copyright (c) 2023 K. Suwatchai (Mobizt) + * + * + * Permission is hereby granted, free of charge, to any person returning a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#if 0 +#ifndef MBFS_CLASS_H +#define MBFS_CLASS_H + +#include +#include "MB_MCU.h" + +#define FS_NO_GLOBALS +#if defined(ESP32) || defined(ESP8266) || defined(MB_ARDUINO_PICO) +#if defined(MBFS_FLASH_FS) || defined(MBFS_SD_FS) +#include +#endif +#endif +#include "MB_FS_Interfaces.h" +#include MB_STRING_INCLUDE_CLASS + +#if defined(MBFS_FLASH_FS) || defined(MBFS_SD_FS) +#include "SPI.h" +#endif + +#if defined(ESP32) && __has_include() +#ifdef _LITTLEFS_H_ +#define MB_FS_USE_POSIX_STAT +#include +namespace mb_fs_ns +{ + inline bool exists(const char *mountPoint, const char *filename) + { + MB_String path = mountPoint; + path += filename; + struct stat st; + return stat(path.c_str(), &st) == 0; + } +}; +#endif +#endif + +using namespace mb_string; + +#if defined(BOARD_HAS_PSRAM) && defined(MB_STRING_USE_PSRAM) +#include +#endif + +#define MB_FS_ERROR_FILE_IO_ERROR -300 +#define MB_FS_ERROR_FILE_NOT_FOUND -301 +#define MB_FS_ERROR_FLASH_STORAGE_IS_NOT_READY -302 +#define MB_FS_ERROR_SD_STORAGE_IS_NOT_READY -303 +#define MB_FS_ERROR_FILE_STILL_OPENED -304 + +typedef enum +{ + mb_fs_mem_storage_type_undefined, + mb_fs_mem_storage_type_flash, + mb_fs_mem_storage_type_sd +} mb_fs_mem_storage_type; + +typedef enum +{ + mb_fs_open_mode_undefined = -1, + mb_fs_open_mode_read = 0, + mb_fs_open_mode_write, + mb_fs_open_mode_append +} mb_fs_open_mode; + +#define mbfs_file_type mb_fs_mem_storage_type +#define mbfs_flash mb_fs_mem_storage_type_flash +#define mbfs_sd mb_fs_mem_storage_type_sd +#define mbfs_undefined mb_fs_mem_storage_type_undefined + +#define mbfs_type (mbfs_file_type) + +#if defined(ARDUINO_ARCH_SAMD) || defined(__AVR_ATmega4809__) || defined(ARDUINO_NANO_RP2040_CONNECT) +#if !defined(MBFS_SDFAT_ENABLED) +struct mbfs_sd_config_info_t +{ + int ss = -1; +}; +#endif +#elif defined(ESP32) || defined(MBFS_SDFAT_ENABLED) + +#if defined(ESP32) +struct mbfs_sd_mmc_config_info_t +{ + const char *mountpoint = ""; + bool mode1bit = false; + bool format_if_mount_failed = false; +}; +#endif + +struct mbfs_sd_config_info_t +{ + int ss = -1; + int sck = -1; + int miso = -1; + int mosi = -1; + uint32_t frequency = 4000000; + +#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) + + SdSpiConfig *sdFatSPIConfig = nullptr; + SdioConfig *sdFatSDIOConfig = nullptr; + +#endif + +#if defined(ESP32) + +#if defined(MBFS_SD_FS) + SPIClass *spiConfig = nullptr; +#endif + mbfs_sd_mmc_config_info_t sdMMCConfig; +#endif + +#if defined(MBFS_SDFAT_ENABLED) + SPIClass *spiConfig = nullptr; +#endif +}; + +#elif defined(ESP8266) || defined(MB_ARDUINO_PICO) +struct mbfs_sd_config_info_t +{ + int ss = -1; +#if defined(MBFS_SD_FS) + SDFSConfig *sdFSConfig = nullptr; +#endif +}; +#else +struct mbfs_sd_config_info_t +{ + int ss = -1; +}; +#endif + +class MB_FS +{ + +public: + MB_FS() {} + ~MB_FS() {} + + struct mbfs_sd_config_info_t sd_config; + + // Assign the SD card interfaces with GPIO pins. + bool sdBegin(int ss = -1, int sck = -1, int miso = -1, int mosi = -1, uint32_t frequency = 4000000) + { + if (sd_rdy) + return true; + +#if defined(MBFS_SD_FS) && defined(MBFS_CARD_TYPE_SD) + sd_config.ss = ss; +#if defined(ESP32) + sd_config.sck = sck; + sd_config.miso = miso; + sd_config.mosi = mosi; + SPI.begin(sck, miso, mosi, ss); + sd_config.frequency = frequency; + return sdSPIBegin(ss, &SPI, frequency); +#elif defined(ESP8266) || defined(ARDUINO_ARCH_SAMD) || defined(__AVR_ATmega4809__) || defined(ARDUINO_NANO_RP2040_CONNECT) + sd_rdy = MBFS_SD_FS.begin(ss); + return sd_rdy; +#elif defined(MB_ARDUINO_PICO) + SDFSConfig c; + c.setCSPin(ss); + c.setSPISpeed(frequency); + MBFS_SD_FS.setConfig(c); + sd_rdy = MBFS_SD_FS.begin(); + return sd_rdy; +#endif + +#endif + return false; + } + +#if defined(ESP32) && defined(MBFS_SD_FS) && defined(MBFS_CARD_TYPE_SD) + + // Assign the SD card interfaces with SPIClass object pointer (ESP32 only). + bool sdSPIBegin(int ss, SPIClass *spiConfig, uint32_t frequency) + { + + if (sd_rdy) + return true; + + sd_config.frequency = frequency; + +#if defined(ESP32) + + sd_config.ss = ss; + + if (spiConfig) + sd_config.spiConfig = spiConfig; + else + sd_config.spiConfig = &SPI; + +#if !defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) + if (ss > -1) + sd_rdy = MBFS_SD_FS.begin(ss, *sd_config.spiConfig, frequency); + else + sd_rdy = MBFS_SD_FS.begin(); +#endif + +#elif defined(ESP8266) || defined(MB_ARDUINO_PICO) + + cfg->_int.sd_config.sck = sck; + + if (ss > -1) + sd_rdy = MBFS_SD_FS.begin(ss); + else + sd_rdy = MBFS_SD_FS.begin(SD_CS_PIN); +#endif + + return sd_rdy; + } + +#endif + +#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) + + // Assign the SD card interfaces with SdSpiConfig object pointer and SPI pins assignment. + bool sdFatBegin(SdSpiConfig *sdFatSPIConfig, int ss, int sck, int miso, int mosi) + { + + if (sd_rdy) + return true; + + if (sdFatSPIConfig) + { + sd_config.sdFatSPIConfig = sdFatSPIConfig; + sd_config.spiConfig = &SPI; + sd_config.ss = ss; + +#if defined(ESP32) + if (ss > -1) + sd_config.spiConfig->begin(sck, miso, mosi, ss); +#endif + + sd_rdy = MBFS_SD_FS.begin(*sd_config.sdFatSPIConfig); + return sd_rdy; + } + + return false; + } + + // Assign the SD card interfaces with SdioConfig object pointer. + bool sdFatBegin(SdioConfig *sdFatSDIOConfig) + { + + if (sd_rdy) + return true; + +#if defined(HAS_SDIO_CLASS) // Default is 0 (no SDIO) in SdFatConfig.h + +#if HAS_SDIO_CLASS + + if (sdFatSDIOConfig) + { + sd_config.sdFatSDIOConfig = sdFatSDIOConfig; + + sd_rdy = MBFS_SD_FS.begin(*sd_config.sdFatSDIOConfig); + return sd_rdy; + } +#endif + +#endif + + return false; + } +#endif + +#if (defined(ESP8266) || defined(MB_ARDUINO_PICO)) && defined(MBFS_SD_FS) + // Assign the SD card interfaces with SDFSConfig object pointer (ESP8266 and Pico only). + bool sdFatBegin(SDFSConfig *sdFSConfig) + { + + if (sd_rdy) + return true; + + if (sdFSConfig) + { + sd_config.sdFSConfig = sdFSConfig; + SDFS.setConfig(*sd_config.sdFSConfig); + sd_rdy = SDFS.begin(); + return sd_rdy; + } + + return false; + } +#endif + + // Assign the SD_MMC card interfaces (ESP32 only). + bool sdMMCBegin(const char *mountpoint, bool mode1bit, bool format_if_mount_failed) + { + + if (sd_rdy) + return true; + +#if defined(ESP32) +#if defined(MBFS_CARD_TYPE_SD_MMC) + + sd_config.sdMMCConfig.mountpoint = mountpoint; + sd_config.sdMMCConfig.mode1bit = mode1bit; + sd_config.sdMMCConfig.format_if_mount_failed = format_if_mount_failed; + + sd_rdy = MBFS_SD_FS.begin(mountpoint, mode1bit, format_if_mount_failed); + return sd_rdy; +#endif +#endif + return false; + } + + // Check the mounting status of Flash storage. + bool flashReady() + { +#if defined MBFS_FLASH_FS + + if (flash_rdy) + return true; + +#if defined(ESP32) + +#if defined(MBFS_FORMAT_FLASH) + flash_rdy = MBFS_FLASH_FS.begin(true); +#else + flash_rdy = MBFS_FLASH_FS.begin(); +#endif + +#elif defined(ESP8266) || defined(MB_ARDUINO_PICO) + flash_rdy = MBFS_FLASH_FS.begin(); +#endif + +#endif + + return flash_rdy; + } + + // Check the mounting status of SD storage. + bool sdReady() + { + +#if defined(MBFS_SD_FS) + + if (sd_rdy) + return true; + +#if defined(ESP32) + +#if defined(MBFS_CARD_TYPE_SD) + + if (!sd_config.spiConfig) + { + if (sd_config.ss > -1) + SPI.begin(sd_config.sck, sd_config.miso, sd_config.mosi, sd_config.ss); + sd_config.spiConfig = &SPI; + } + +#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) + + if (!sd_rdy) + { + if (sd_config.sdFatSPIConfig) + sd_rdy = MBFS_SD_FS.begin(*sd_config.sdFatSPIConfig); + else if (sd_config.sdFatSDIOConfig) + sd_rdy = MBFS_SD_FS.begin(*sd_config.sdFatSDIOConfig); + } + +#else + if (!sd_rdy) + sd_rdy = sdSPIBegin(sd_config.ss, sd_config.spiConfig, sd_config.frequency); + +#endif + +#elif defined(MBFS_CARD_TYPE_SD_MMC) + if (!sd_rdy) + sd_rdy = sdMMCBegin(sd_config.sdMMCConfig.mountpoint, sd_config.sdMMCConfig.mode1bit, sd_config.sdMMCConfig.format_if_mount_failed); +#endif + +#elif defined(ESP8266) || defined(MB_ARDUINO_PICO) + if (!sd_rdy) + { + if (sd_config.sdFSConfig) + sd_rdy = sdFatBegin(sd_config.sdFSConfig); + else + sd_rdy = sdBegin(sd_config.ss); + } + +#elif defined(ARDUINO_ARCH_SAMD) || defined(__AVR_ATmega4809__) || defined(ARDUINO_NANO_RP2040_CONNECT) + if (!sd_rdy) + sd_rdy = sdBegin(sd_config.ss); +#endif + +#endif + + return sd_rdy; + } + + // Check the mounting status of Flash or SD storage with mb_fs_mem_storage_type. + bool checkStorageReady(mbfs_file_type type) + { + +#if defined(MBFS_USE_FILE_STORAGE) + if (type == mbfs_flash) + { + if (!flash_rdy) + flashReady(); + return flash_rdy; + } + else if (type == mbfs_sd) + { + if (!sd_rdy) + sdReady(); + return sd_rdy; + } +#endif + + return false; + } + + // Open file for read or write with file name, mb_fs_mem_storage_type and mb_fs_open_mode. + // return size of file (read) or 0 (write) or negative value for error + int open(const MB_String &filename, mbfs_file_type type, mb_fs_open_mode mode) + { + +#if defined(MBFS_USE_FILE_STORAGE) + + if (!checkStorageReady(type)) + { + if (type == mbfs_flash) + return MB_FS_ERROR_FLASH_STORAGE_IS_NOT_READY; + else if (type == mbfs_sd) + return MB_FS_ERROR_SD_STORAGE_IS_NOT_READY; + else + return MB_FS_ERROR_FILE_IO_ERROR; + } + + if (mode == mb_fs_open_mode_read) + { + if (!existed(filename.c_str(), type)) + return MB_FS_ERROR_FILE_NOT_FOUND; + } + + int ret = openFile(filename, type, mode); + + if (ret < 0) + return ret; + + if (ready(type)) + return ret; + +#endif + return MB_FS_ERROR_FILE_IO_ERROR; + } + + // Check if file is already open. + bool ready(mbfs_file_type type) + { +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + return true; +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && mb_sdFs) + return true; +#endif + return false; + } + + // Get file for read/write with file name, mb_fs_mem_storage_type and mb_fs_open_mode. + int size(mbfs_file_type type) + { + int size = 0; + +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + size = mb_flashFs.size(); +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && mb_sdFs) + size = mb_sdFs.size(); +#endif + return size; + } + + // Check if file is ready to read/write. + int available(mbfs_file_type type) + { + int available = 0; + +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + available = mb_flashFs.available(); +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && mb_sdFs) + available = mb_sdFs.available(); +#endif + return available; + } + + // Read byte array. Return the number of bytes that completed read or negative value for error. + int read(mbfs_file_type type, uint8_t *buf, size_t len) + { + int read = 0; +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + read = mb_flashFs.read(buf, len); +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && mb_sdFs) + read = mb_sdFs.read(buf, len); +#endif + return read; + } + + // Print char array. Return the number of bytes that completed write or negative value for error. + int print(mbfs_file_type type, const char *str) + { + int write = 0; +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + write = mb_flashFs.print(str); +#endif +#if defined(MBFS_SD_FS) + + if (type == mbfs_sd && mb_sdFs) + write = mb_sdFs.print(str); +#endif + return write; + } + + // Print char array with new line. Return the number of bytes that completed write or negative value for error. + int println(mbfs_file_type type, const char *str) + { + int write = print(type, str); + if (write == (int)strlen(str)) + write += print(type, (const char *)MBSTRING_FLASH_MCR("\n")); + return write; + } + + // Print integer. Return the number of bytes that completed write or negative value for error. + int print(mbfs_file_type type, int v) + { + int write = 0; +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + write = mb_flashFs.print(v); +#endif +#if defined(MBFS_SD_FS) + + if (type == mbfs_sd && mb_sdFs) + write = mb_sdFs.print(v); +#endif + return write; + } + + // Print integer with newline. Return the number of bytes that completed write or negative value for error. + int println(mbfs_file_type type, int v) + { + int write = print(type, v); + if (write > 0) + write += print(type, (const char *)MBSTRING_FLASH_MCR("\n")); + return write; + } + + int print(mbfs_file_type type, unsigned int v) + { + int write = 0; +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + write = mb_flashFs.print(v); +#endif +#if defined(MBFS_SD_FS) + + if (type == mbfs_sd && mb_sdFs) + write = mb_sdFs.print(v); +#endif + return write; + } + + // Print integer with newline. Return the number of bytes that completed write or negative value for error. + int println(mbfs_file_type type, unsigned int v) + { + int write = print(type, v); + if (write > 0) + write += print(type, (const char *)MBSTRING_FLASH_MCR("\n")); + return write; + } + + // Write byte array. Return the number of bytes that completed write or negative value for error. + int write(mbfs_file_type type, uint8_t *buf, size_t len) + { + int write = 0; +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + write = mb_flashFs.write(buf, len); +#endif +#if defined(MBFS_SD_FS) + + if (type == mbfs_sd && mb_sdFs) + write = mb_sdFs.write(buf, len); +#endif + return write; + } + + // Close file. + void close(mbfs_file_type type) + { + +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs && flash_opened) + { + mb_flashFs.close(); + flash_filename_crc = 0; + flash_opened = false; + flash_open_mode = mb_fs_open_mode_undefined; + } +#endif + +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && mb_sdFs && sd_opened) + { + mb_sdFs.close(); + sd_filename_crc = 0; + sd_opened = false; + sd_open_mode = mb_fs_open_mode_undefined; + } +#endif + } + + // Check file existence. + bool existed(const MB_String &filename, mbfs_file_type type) + { + + if (!checkStorageReady(type)) + return false; + +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash) + { + +// The workaround for ESP32 LittleFS when calling vfs_api.cpp open() issue. +// See https://github.com/espressif/arduino-esp32/issues/7615 +#if defined(MB_FS_USE_POSIX_STAT) + return mb_fs_ns::exists("/littlefs", filename.c_str()); +#else + return MBFS_FLASH_FS.exists(filename.c_str()); +#endif + } + +#endif + +#if defined(MBFS_SD_FS) + if (type == mbfs_sd) + { +#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) + MBFS_SD_FILE file; + bool ret = file.open(filename.c_str(), O_RDONLY); + file.close(); + return ret; +#else + return MBFS_SD_FS.exists(filename.c_str()); +#endif + } +#endif + + return false; + } + + // Seek to position in file. + bool seek(mbfs_file_type type, int pos) + { + +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + return mb_flashFs.seek(pos); +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && mb_sdFs) + return mb_sdFs.seek(pos); +#endif + + return false; + } + + // Read byte. Return the 1 for completed read or negative value for error. + int read(mbfs_file_type type) + { +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + return mb_flashFs.read(); +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && mb_sdFs) + return mb_sdFs.read(); +#endif + return -1; + } + + // Write byte. Return the 1 for completed write or negative value for error. + int write(mbfs_file_type type, uint8_t v) + { +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + return mb_flashFs.write(v); +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && mb_sdFs) + return mb_sdFs.write(v); +#endif + return -1; + } + + bool remove(const MB_String &filename, mbfs_file_type type) + { + if (!checkStorageReady(type)) + return false; + +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && !flashReady()) + return false; +#endif + +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && !sdReady()) + return false; +#endif + + if (!existed(filename, type)) + return true; + +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash) + return MBFS_FLASH_FS.remove(filename.c_str()); +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd) + { +#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) + if (mb_sdFs.open(filename.c_str(), O_RDWR | O_CREAT | O_APPEND)) + { + mb_sdFs.remove(); + mb_sdFs.close(); + return true; + } +#else + return MBFS_SD_FS.remove(filename.c_str()); +#endif + } + +#endif + return false; + } + +// Get the Flash file instance. +#if defined(MBFS_FLASH_FS) + fs::File &getFlashFile() + { + return mb_flashFs; + } +#endif + +// Get the SD file instance. +#if defined(MBFS_SD_FS) + MBFS_SD_FILE &getSDFile() + { + return mb_sdFs; + } +#endif + + // Get name of opened file. + const char *name(mbfs_file_type type) + { +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + return flash_file.c_str(); +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && mb_sdFs) + return sd_file.c_str(); +#endif + + return ""; + } + + // Calculate CRC16 of byte array. + uint16_t calCRC(const char *buf) + { + uint8_t x; + uint16_t crc = 0xFFFF; + + int length = (int)strlen(buf); + + while (length--) + { + x = crc >> 8 ^ *buf++; + x ^= x >> 4; + crc = (crc << 8) ^ ((uint16_t)(x << 12)) ^ ((uint16_t)(x << 5)) ^ ((uint16_t)x); + } + return crc; + } + + // Free reserved memory at pointer. + void delP(void *ptr) + { + void **p = (void **)ptr; + if (*p) + { + free(*p); + *p = 0; + } + } + + // Allocate memory + void *newP(size_t len, bool clear = true) + { + void *p; + size_t newLen = getReservedLen(len); +#if defined(BOARD_HAS_PSRAM) && defined(MB_STRING_USE_PSRAM) + + if (ESP.getPsramSize() > 0) + p = (void *)ps_malloc(newLen); + else + p = (void *)malloc(newLen); + + if (!p) + return NULL; + +#else + +#if defined(ESP8266_USE_EXTERNAL_HEAP) + ESP.setExternalHeap(); +#endif + + p = (void *)malloc(newLen); + bool nn = p ? true : false; + +#if defined(ESP8266_USE_EXTERNAL_HEAP) + ESP.resetHeap(); +#endif + + if (!nn) + return NULL; + +#endif + if (clear) + memset(p, 0, newLen); + return p; + } + + size_t getReservedLen(size_t len) + { + int blen = len + 1; + + int newlen = (blen / 4) * 4; + + if (newlen < blen) + newlen += 4; + + return (size_t)newlen; + } + + void createDirs(MB_String dirs, mbfs_file_type type) + { + if (!longNameSupported()) + return; + + MB_String dir; + int count = 0; + int lastPos = 0; + for (size_t i = 0; i < dirs.length(); i++) + { + dir.append(1, dirs[i]); + count++; + if (dirs[i] == '/' && i > 0) + { + if (dir.length() > 0) + { + + lastPos = dir.length() - 1; + +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash) + MBFS_FLASH_FS.mkdir(dir.substr(0, dir.length() - 1).c_str()); +#endif + +#if defined(MBFS_SD_FS) + if (type == mbfs_sd) + MBFS_SD_FS.mkdir(dir.substr(0, dir.length() - 1).c_str()); +#endif + } + count = 0; + } + } + + if (count > 0) + { + if (dir.find('.', lastPos) == MB_String::npos) + { +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash) + MBFS_FLASH_FS.mkdir(dir.c_str()); +#endif + +#if defined(MBFS_SD_FS) + if (type == mbfs_sd) + MBFS_SD_FS.mkdir(dir.c_str()); +#endif + } + } + + dir.clear(); + } + + bool longNameSupported() + { + +#if defined(MBFS_SDFAT_ENABLED) || defined(MBFS_FLASH_FS) + return true; +#endif + +#if defined(MBFS_SD_FS) && (defined(ESP32) || defined(ESP8266) || defined(MB_ARDUINO_PICO)) + return true; +#endif + + return false; + } + +private: + uint16_t flash_filename_crc = 0; + uint16_t sd_filename_crc = 0; + MB_String flash_file, sd_file; + mb_fs_open_mode flash_open_mode = mb_fs_open_mode_undefined; + mb_fs_open_mode sd_open_mode = mb_fs_open_mode_undefined; + bool flash_opened = false; + bool sd_opened = false; + bool sd_rdy = false; + bool flash_rdy = false; + uint16_t loopCount = 0; + +#if defined(MBFS_FLASH_FS) + fs::File mb_flashFs; +#endif +#if defined(MBFS_SD_FS) + MBFS_SD_FILE mb_sdFs; +#endif + + int openFile(const MB_String &filename, mb_fs_mem_storage_type type, mb_fs_open_mode mode) + { + +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash) + return openFlashFile(filename, mode); +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd) + return openSDFile(filename, mode); +#endif + return MB_FS_ERROR_FILE_IO_ERROR; + } + + int openSDFile(const MB_String &filename, mb_fs_open_mode mode) + { + int ret = MB_FS_ERROR_FILE_IO_ERROR; + +#if defined(MBFS_SD_FS) + + if (mode == mb_fs_open_mode_read || mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) + { + uint16_t crc = calCRC(filename.c_str()); + + if (mode == sd_open_mode && flash_filename_crc == crc && sd_opened) // same sd file opened, leave it + return MB_FS_ERROR_FILE_STILL_OPENED; + + if (sd_opened) + close(mbfs_sd); // sd file opened, close it + + flash_filename_crc = crc; + } + +#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) + + if (mode == mb_fs_open_mode_read) + { + if (mb_sdFs.open(filename.c_str(), O_RDONLY)) + { + sd_file = filename; + sd_opened = true; + sd_open_mode = mode; + ret = mb_sdFs.size(); + } + } + else if (mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) + { + if (mode == mb_fs_open_mode_write) + remove(filename, mb_fs_mem_storage_type_sd); + + createDirs(filename, mb_fs_mem_storage_type_sd); + if (mb_sdFs.open(filename.c_str(), O_RDWR | O_CREAT | O_APPEND)) + { + sd_file = filename; + sd_opened = true; + sd_open_mode = mode; + ret = 0; + } + } + +#else + + if (mode == mb_fs_open_mode_read) + { +#if defined(ESP32) || defined(ESP8266) + mb_sdFs = MBFS_SD_FS.open(filename.c_str(), FILE_READ); +#else + mb_sdFs = MBFS_SD_FS.open(filename.c_str(), "r"); +#endif + if (mb_sdFs) + { + sd_file = filename; + sd_opened = true; + sd_open_mode = mode; + ret = mb_sdFs.size(); + } + } + else if (mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) + { + if (mode == mb_fs_open_mode_write) + remove(filename, mb_fs_mem_storage_type_sd); + + createDirs(filename, mb_fs_mem_storage_type_sd); +#if defined(ESP32) + if (mode == mb_fs_open_mode_write) + mb_sdFs = MBFS_SD_FS.open(filename.c_str(), FILE_WRITE); + else + mb_sdFs = MBFS_SD_FS.open(filename.c_str(), FILE_APPEND); +#elif defined(ESP8266) + mb_sdFs = MBFS_SD_FS.open(filename.c_str(), FILE_WRITE); +#else + if (mode == mb_fs_open_mode_write) + mb_sdFs = MBFS_SD_FS.open(filename.c_str(), "w"); + else + mb_sdFs = MBFS_SD_FS.open(filename.c_str(), "a"); +#endif + + if (mb_sdFs) + { + sd_file = filename; + sd_opened = true; + sd_open_mode = mode; + ret = 0; + } + } +#endif + +#endif + return ret; + } + + int openFlashFile(const MB_String &filename, mb_fs_open_mode mode) + { + int ret = MB_FS_ERROR_FILE_IO_ERROR; + +#if defined(MBFS_FLASH_FS) + + if (mode == mb_fs_open_mode_read || mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) + { + uint16_t crc = calCRC(filename.c_str()); + if (mode == flash_open_mode && sd_filename_crc == crc && flash_opened) // same flash file opened, leave it + return MB_FS_ERROR_FILE_STILL_OPENED; + + if (flash_opened) + close(mbfs_flash); // flash file opened, close it + + sd_filename_crc = crc; + } + + if (mode == mb_fs_open_mode_read) + { + mb_flashFs = MBFS_FLASH_FS.open(filename.c_str(), "r"); + if (mb_flashFs) + { + flash_file = filename; + flash_opened = true; + flash_open_mode = mode; + ret = mb_flashFs.size(); + } + } + else if (mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) + { + if (mode == mb_fs_open_mode_write) + remove(filename, mb_fs_mem_storage_type_flash); + + createDirs(filename, mb_fs_mem_storage_type_flash); + if (mode == mb_fs_open_mode_write) + mb_flashFs = MBFS_FLASH_FS.open(filename.c_str(), "w"); + else + mb_flashFs = MBFS_FLASH_FS.open(filename.c_str(), "a"); + + if (mb_flashFs) + { + flash_file = filename; + flash_opened = true; + flash_open_mode = mode; + ret = 0; + } + } + +#endif + return ret; + } +}; + +#endif +#endif \ No newline at end of file diff --git a/tasmota/tasmota_xdrv_driver/xdrv_01_2_webserver_esp32_mail.ino b/tasmota/tasmota_xdrv_driver/xdrv_01_2_webserver_esp32_mail.ino index 3f26baa0d..c1588ec3b 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_01_2_webserver_esp32_mail.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_01_2_webserver_esp32_mail.ino @@ -296,6 +296,8 @@ void attach_File(char *path) { att.descr.mime = "application/octet-stream"; //binary data #if ESP_MAIL_VERSION_NUM<30409 att.file.storage_type = esp_mail_file_storage_type_univ; +#else + att.file.storage_type = esp_mail_file_storage_type_flash; #endif att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64; email_mptr->addAttachment(att);