| 
									
										
										
										
											2021-11-06 17:31:05 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2023-07-17 11:59:28 +02:00
										 |  |  |  * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD | 
					
						
							| 
									
										
										
										
											2021-11-06 17:31:05 +08:00
										 |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: Apache-2.0 | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "esp_spiffs.h"
 | 
					
						
							|  |  |  | #include "spiffs.h"
 | 
					
						
							|  |  |  | #include "spiffs_nucleus.h"
 | 
					
						
							|  |  |  | #include "esp_log.h"
 | 
					
						
							|  |  |  | #include "esp_partition.h"
 | 
					
						
							| 
									
										
										
										
											2022-06-27 15:24:07 +08:00
										 |  |  | #include "spi_flash_mmap.h"
 | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  | #include "esp_image_format.h"
 | 
					
						
							|  |  |  | #include "freertos/FreeRTOS.h"
 | 
					
						
							|  |  |  | #include "freertos/task.h"
 | 
					
						
							|  |  |  | #include "freertos/semphr.h"
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | #include <dirent.h>
 | 
					
						
							|  |  |  | #include <sys/errno.h>
 | 
					
						
							|  |  |  | #include <sys/fcntl.h>
 | 
					
						
							|  |  |  | #include <sys/lock.h>
 | 
					
						
							|  |  |  | #include "esp_vfs.h"
 | 
					
						
							|  |  |  | #include "esp_err.h"
 | 
					
						
							| 
									
										
										
										
											2021-09-28 14:12:56 +08:00
										 |  |  | #include "esp_rom_spiflash.h"
 | 
					
						
							| 
									
										
										
										
											2020-12-30 16:10:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-22 16:47:30 +08:00
										 |  |  | #include "spiffs_api.h"
 | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-21 16:51:44 +08:00
										 |  |  | static const char* TAG = "SPIFFS"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 00:17:11 +08:00
										 |  |  | #ifdef CONFIG_SPIFFS_USE_MTIME
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:58:54 +08:00
										 |  |  | #ifdef CONFIG_SPIFFS_MTIME_WIDE_64_BITS
 | 
					
						
							|  |  |  | typedef time_t spiffs_time_t; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | typedef unsigned long spiffs_time_t; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | _Static_assert(CONFIG_SPIFFS_META_LENGTH >= sizeof(spiffs_time_t), | 
					
						
							|  |  |  |         "SPIFFS_META_LENGTH size should be >= sizeof(spiffs_time_t)"); | 
					
						
							| 
									
										
										
										
											2017-11-22 00:17:11 +08:00
										 |  |  | #endif //CONFIG_SPIFFS_USE_MTIME
 | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-25 15:23:59 +02:00
										 |  |  | _Static_assert(ESP_SPIFFS_PATH_MAX == ESP_VFS_PATH_MAX, | 
					
						
							|  |  |  |                "SPIFFS max path length has to be aligned with the VFS max path length"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @brief SPIFFS DIR structure | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  |     DIR dir;            /*!< VFS DIR struct */ | 
					
						
							|  |  |  |     spiffs_DIR d;       /*!< SPIFFS DIR struct */ | 
					
						
							|  |  |  |     struct dirent e;    /*!< Last open dirent */ | 
					
						
							|  |  |  |     long offset;        /*!< Offset of the current dirent */ | 
					
						
							|  |  |  |     char path[SPIFFS_OBJ_NAME_LEN]; /*!< Requested directory name */ | 
					
						
							|  |  |  | } vfs_spiffs_dir_t; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-19 16:24:53 +02:00
										 |  |  | static int spiffs_res_to_errno(s32_t fr); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  | static int vfs_spiffs_open(void* ctx, const char * path, int flags, int mode); | 
					
						
							|  |  |  | static ssize_t vfs_spiffs_write(void* ctx, int fd, const void * data, size_t size); | 
					
						
							|  |  |  | static ssize_t vfs_spiffs_read(void* ctx, int fd, void * dst, size_t size); | 
					
						
							|  |  |  | static int vfs_spiffs_close(void* ctx, int fd); | 
					
						
							|  |  |  | static off_t vfs_spiffs_lseek(void* ctx, int fd, off_t offset, int mode); | 
					
						
							|  |  |  | static int vfs_spiffs_fstat(void* ctx, int fd, struct stat * st); | 
					
						
							| 
									
										
										
										
											2020-03-20 13:24:18 +01:00
										 |  |  | #ifdef CONFIG_VFS_SUPPORT_DIR
 | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  | static int vfs_spiffs_stat(void* ctx, const char * path, struct stat * st); | 
					
						
							|  |  |  | static int vfs_spiffs_unlink(void* ctx, const char *path); | 
					
						
							|  |  |  | static int vfs_spiffs_link(void* ctx, const char* n1, const char* n2); | 
					
						
							|  |  |  | static int vfs_spiffs_rename(void* ctx, const char *src, const char *dst); | 
					
						
							|  |  |  | static DIR* vfs_spiffs_opendir(void* ctx, const char* name); | 
					
						
							|  |  |  | static int vfs_spiffs_closedir(void* ctx, DIR* pdir); | 
					
						
							|  |  |  | static struct dirent* vfs_spiffs_readdir(void* ctx, DIR* pdir); | 
					
						
							|  |  |  | static int vfs_spiffs_readdir_r(void* ctx, DIR* pdir, | 
					
						
							|  |  |  |                                 struct dirent* entry, struct dirent** out_dirent); | 
					
						
							|  |  |  | static long vfs_spiffs_telldir(void* ctx, DIR* pdir); | 
					
						
							|  |  |  | static void vfs_spiffs_seekdir(void* ctx, DIR* pdir, long offset); | 
					
						
							|  |  |  | static int vfs_spiffs_mkdir(void* ctx, const char* name, mode_t mode); | 
					
						
							|  |  |  | static int vfs_spiffs_rmdir(void* ctx, const char* name); | 
					
						
							| 
									
										
										
										
											2022-03-18 15:19:18 +05:30
										 |  |  | static int vfs_spiffs_truncate(void* ctx, const char *path, off_t length); | 
					
						
							|  |  |  | static int vfs_spiffs_ftruncate(void* ctx, int fd, off_t length); | 
					
						
							| 
									
										
										
										
											2020-02-05 03:00:22 +08:00
										 |  |  | #ifdef CONFIG_SPIFFS_USE_MTIME
 | 
					
						
							| 
									
										
										
										
											2018-10-25 11:53:52 +02:00
										 |  |  | static int vfs_spiffs_utime(void *ctx, const char *path, const struct utimbuf *times); | 
					
						
							| 
									
										
										
										
											2020-03-20 13:24:18 +01:00
										 |  |  | #endif // CONFIG_SPIFFS_USE_MTIME
 | 
					
						
							|  |  |  | #endif // CONFIG_VFS_SUPPORT_DIR
 | 
					
						
							|  |  |  | static void vfs_spiffs_update_mtime(spiffs *fs, spiffs_file f); | 
					
						
							|  |  |  | static time_t vfs_spiffs_get_mtime(const spiffs_stat* s); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | static esp_spiffs_t * _efs[CONFIG_SPIFFS_MAX_PARTITIONS]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void esp_spiffs_free(esp_spiffs_t ** efs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     esp_spiffs_t * e = *efs; | 
					
						
							|  |  |  |     if (*efs == NULL) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     *efs = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (e->fs) { | 
					
						
							|  |  |  |         SPIFFS_unmount(e->fs); | 
					
						
							|  |  |  |         free(e->fs); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     vSemaphoreDelete(e->lock); | 
					
						
							|  |  |  |     free(e->fds); | 
					
						
							|  |  |  |     free(e->cache); | 
					
						
							|  |  |  |     free(e->work); | 
					
						
							|  |  |  |     free(e); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static esp_err_t esp_spiffs_by_label(const char* label, int * index){ | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  |     esp_spiffs_t * p; | 
					
						
							|  |  |  |     for (i = 0; i < CONFIG_SPIFFS_MAX_PARTITIONS; i++) { | 
					
						
							|  |  |  |         p = _efs[i]; | 
					
						
							|  |  |  |         if (p) { | 
					
						
							|  |  |  |             if (!label && !p->by_label) { | 
					
						
							|  |  |  |                 *index = i; | 
					
						
							|  |  |  |                 return ESP_OK; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (label && p->by_label && strncmp(label, p->partition->label, 17) == 0) { | 
					
						
							|  |  |  |                 *index = i; | 
					
						
							|  |  |  |                 return ESP_OK; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return ESP_ERR_NOT_FOUND; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static esp_err_t esp_spiffs_get_empty(int * index){ | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  |     for (i = 0; i < CONFIG_SPIFFS_MAX_PARTITIONS; i++) { | 
					
						
							|  |  |  |         if (_efs[i] == NULL) { | 
					
						
							|  |  |  |             *index = i; | 
					
						
							|  |  |  |             return ESP_OK; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return ESP_ERR_NOT_FOUND; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static esp_err_t esp_spiffs_init(const esp_vfs_spiffs_conf_t* conf) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int index; | 
					
						
							|  |  |  |     //find if such partition is already mounted
 | 
					
						
							|  |  |  |     if (esp_spiffs_by_label(conf->partition_label, &index) == ESP_OK) { | 
					
						
							|  |  |  |         return ESP_ERR_INVALID_STATE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (esp_spiffs_get_empty(&index) != ESP_OK) { | 
					
						
							|  |  |  |         ESP_LOGE(TAG, "max mounted partitions reached"); | 
					
						
							|  |  |  |         return ESP_ERR_INVALID_STATE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-28 23:17:54 +08:00
										 |  |  |     uint32_t flash_page_size = g_rom_flashchip.page_size; | 
					
						
							|  |  |  |     uint32_t log_page_size = CONFIG_SPIFFS_PAGE_SIZE; | 
					
						
							|  |  |  |     if (log_page_size % flash_page_size != 0) { | 
					
						
							| 
									
										
										
										
											2022-10-06 16:16:32 +02:00
										 |  |  |         ESP_LOGE(TAG, "SPIFFS_PAGE_SIZE is not multiple of flash chip page size (%" PRIu32 ")", | 
					
						
							| 
									
										
										
										
											2018-01-28 23:17:54 +08:00
										 |  |  |                 flash_page_size); | 
					
						
							|  |  |  |         return ESP_ERR_INVALID_ARG; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     esp_partition_subtype_t subtype = conf->partition_label ? | 
					
						
							|  |  |  |             ESP_PARTITION_SUBTYPE_ANY : ESP_PARTITION_SUBTYPE_DATA_SPIFFS; | 
					
						
							| 
									
										
										
										
											2018-05-22 16:47:30 +08:00
										 |  |  |     const esp_partition_t* partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |                                       subtype, conf->partition_label); | 
					
						
							|  |  |  |     if (!partition) { | 
					
						
							|  |  |  |         ESP_LOGE(TAG, "spiffs partition could not be found"); | 
					
						
							|  |  |  |         return ESP_ERR_NOT_FOUND; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (partition->encrypted) { | 
					
						
							|  |  |  |         ESP_LOGE(TAG, "spiffs can not run on encrypted partition"); | 
					
						
							|  |  |  |         return ESP_ERR_INVALID_STATE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-04 09:53:43 +02:00
										 |  |  |     const size_t flash_erase_sector_size = g_rom_flashchip.sector_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Older versions of IDF allowed creating misaligned data partitions.
 | 
					
						
							|  |  |  |      * This would result in hard-to-diagnose SPIFFS failures due to failing erase operations. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (partition->address % flash_erase_sector_size != 0) { | 
					
						
							|  |  |  |         ESP_LOGE(TAG, "spiffs partition is not aligned to flash sector size, please check the partition table"); | 
					
						
							|  |  |  |         /* No return intentional to avoid accidentally breaking applications
 | 
					
						
							|  |  |  |          * which used misaligned read-only SPIFFS partitions. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Check if the SPIFFS internal data types are wide enough.
 | 
					
						
							|  |  |  |      * Casting -1 to the unsigned type produces the maximum value the type can hold. | 
					
						
							|  |  |  |      * All the checks here are based on comments for the said data types in spiffs_config.h. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (partition->size / flash_erase_sector_size > (spiffs_block_ix) -1) { | 
					
						
							|  |  |  |         ESP_LOGE(TAG, "spiffs partition is too large for spiffs_block_ix type"); | 
					
						
							|  |  |  |         return ESP_ERR_INVALID_ARG; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (partition->size / log_page_size > (spiffs_page_ix) -1) { | 
					
						
							|  |  |  |         /* For 256 byte pages the largest partition is 16MB, but larger partitions can be supported
 | 
					
						
							|  |  |  |          * by increasing the page size (reducing the number of pages). | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         ESP_LOGE(TAG, "spiffs partition is too large for spiffs_page_ix type. Please increase CONFIG_SPIFFS_PAGE_SIZE."); | 
					
						
							|  |  |  |         return ESP_ERR_INVALID_ARG; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (2 + 2 * (partition->size / (2 * log_page_size)) > (spiffs_obj_id) -1) { | 
					
						
							|  |  |  |         ESP_LOGE(TAG, "spiffs partition is too large for spiffs_obj_id type. Please increase CONFIG_SPIFFS_PAGE_SIZE."); | 
					
						
							|  |  |  |         return ESP_ERR_INVALID_ARG; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (partition->size / log_page_size - 1 > (spiffs_span_ix) -1) { | 
					
						
							|  |  |  |         ESP_LOGE(TAG, "spiffs partition is too large for spiffs_span_ix type. Please increase CONFIG_SPIFFS_PAGE_SIZE."); | 
					
						
							|  |  |  |         return ESP_ERR_INVALID_ARG; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     esp_spiffs_t * efs = calloc(sizeof(esp_spiffs_t), 1); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     if (efs == NULL) { | 
					
						
							|  |  |  |         ESP_LOGE(TAG, "esp_spiffs could not be malloced"); | 
					
						
							|  |  |  |         return ESP_ERR_NO_MEM; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     efs->cfg.hal_erase_f       = spiffs_api_erase; | 
					
						
							|  |  |  |     efs->cfg.hal_read_f        = spiffs_api_read; | 
					
						
							|  |  |  |     efs->cfg.hal_write_f       = spiffs_api_write; | 
					
						
							| 
									
										
										
										
											2022-04-04 09:53:43 +02:00
										 |  |  |     efs->cfg.log_block_size    = flash_erase_sector_size; | 
					
						
							| 
									
										
										
										
											2018-01-28 23:17:54 +08:00
										 |  |  |     efs->cfg.log_page_size     = log_page_size; | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     efs->cfg.phys_addr         = 0; | 
					
						
							| 
									
										
										
										
											2022-04-04 09:53:43 +02:00
										 |  |  |     efs->cfg.phys_erase_block  = flash_erase_sector_size; | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     efs->cfg.phys_size         = partition->size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     efs->by_label = conf->partition_label != NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     efs->lock = xSemaphoreCreateMutex(); | 
					
						
							|  |  |  |     if (efs->lock == NULL) { | 
					
						
							|  |  |  |         ESP_LOGE(TAG, "mutex lock could not be created"); | 
					
						
							|  |  |  |         esp_spiffs_free(&efs); | 
					
						
							|  |  |  |         return ESP_ERR_NO_MEM; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     efs->fds_sz = conf->max_files * sizeof(spiffs_fd); | 
					
						
							| 
									
										
										
										
											2022-04-04 09:53:43 +02:00
										 |  |  |     efs->fds = calloc(efs->fds_sz, 1); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     if (efs->fds == NULL) { | 
					
						
							| 
									
										
										
										
											2022-04-04 09:53:43 +02:00
										 |  |  |         ESP_LOGE(TAG, "fd buffer could not be allocated"); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |         esp_spiffs_free(&efs); | 
					
						
							|  |  |  |         return ESP_ERR_NO_MEM; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if SPIFFS_CACHE
 | 
					
						
							|  |  |  |     efs->cache_sz = sizeof(spiffs_cache) + conf->max_files * (sizeof(spiffs_cache_page) | 
					
						
							|  |  |  |                           + efs->cfg.log_page_size); | 
					
						
							| 
									
										
										
										
											2022-04-04 09:53:43 +02:00
										 |  |  |     efs->cache = calloc(efs->cache_sz, 1); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     if (efs->cache == NULL) { | 
					
						
							| 
									
										
										
										
											2022-04-04 09:53:43 +02:00
										 |  |  |         ESP_LOGE(TAG, "cache buffer could not be allocated"); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |         esp_spiffs_free(&efs); | 
					
						
							|  |  |  |         return ESP_ERR_NO_MEM; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const uint32_t work_sz = efs->cfg.log_page_size * 2; | 
					
						
							| 
									
										
										
										
											2022-04-04 09:53:43 +02:00
										 |  |  |     efs->work = calloc(work_sz, 1); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     if (efs->work == NULL) { | 
					
						
							| 
									
										
										
										
											2022-04-04 09:53:43 +02:00
										 |  |  |         ESP_LOGE(TAG, "work buffer could not be allocated"); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |         esp_spiffs_free(&efs); | 
					
						
							|  |  |  |         return ESP_ERR_NO_MEM; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-04 09:53:43 +02:00
										 |  |  |     efs->fs = calloc(sizeof(spiffs), 1); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     if (efs->fs == NULL) { | 
					
						
							| 
									
										
										
										
											2022-04-04 09:53:43 +02:00
										 |  |  |         ESP_LOGE(TAG, "spiffs could not be allocated"); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |         esp_spiffs_free(&efs); | 
					
						
							|  |  |  |         return ESP_ERR_NO_MEM; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     efs->fs->user_data = (void *)efs; | 
					
						
							|  |  |  |     efs->partition = partition; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-22 16:47:30 +08:00
										 |  |  |     s32_t res = SPIFFS_mount(efs->fs, &efs->cfg, efs->work, efs->fds, efs->fds_sz, | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |                             efs->cache, efs->cache_sz, spiffs_api_check); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (conf->format_if_mount_failed && res != SPIFFS_OK) { | 
					
						
							| 
									
										
										
										
											2022-10-06 16:16:32 +02:00
										 |  |  |         ESP_LOGW(TAG, "mount failed, %" PRId32 ". formatting...", SPIFFS_errno(efs->fs)); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |         SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |         res = SPIFFS_format(efs->fs); | 
					
						
							|  |  |  |         if (res != SPIFFS_OK) { | 
					
						
							| 
									
										
										
										
											2022-10-06 16:16:32 +02:00
										 |  |  |             ESP_LOGE(TAG, "format failed, %" PRId32, SPIFFS_errno(efs->fs)); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |             SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |             esp_spiffs_free(&efs); | 
					
						
							|  |  |  |             return ESP_FAIL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-05-22 16:47:30 +08:00
										 |  |  |         res = SPIFFS_mount(efs->fs, &efs->cfg, efs->work, efs->fds, efs->fds_sz, | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |                             efs->cache, efs->cache_sz, spiffs_api_check); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (res != SPIFFS_OK) { | 
					
						
							| 
									
										
										
										
											2022-10-06 16:16:32 +02:00
										 |  |  |         ESP_LOGE(TAG, "mount failed, %" PRId32, SPIFFS_errno(efs->fs)); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |         SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |         esp_spiffs_free(&efs); | 
					
						
							|  |  |  |         return ESP_FAIL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     _efs[index] = efs; | 
					
						
							|  |  |  |     return ESP_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool esp_spiffs_mounted(const char* partition_label) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int index; | 
					
						
							|  |  |  |     if (esp_spiffs_by_label(partition_label, &index) != ESP_OK) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return (SPIFFS_mounted(_efs[index]->fs)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | esp_err_t esp_spiffs_info(const char* partition_label, size_t *total_bytes, size_t *used_bytes) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int index; | 
					
						
							|  |  |  |     if (esp_spiffs_by_label(partition_label, &index) != ESP_OK) { | 
					
						
							|  |  |  |         return ESP_ERR_INVALID_STATE; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-11-06 15:00:07 +11:00
										 |  |  |     SPIFFS_info(_efs[index]->fs, (uint32_t *)total_bytes, (uint32_t *)used_bytes); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     return ESP_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-19 16:24:53 +02:00
										 |  |  | esp_err_t esp_spiffs_check(const char* partition_label) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int index; | 
					
						
							|  |  |  |     if (esp_spiffs_by_label(partition_label, &index) != ESP_OK) { | 
					
						
							|  |  |  |         return ESP_ERR_INVALID_STATE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (SPIFFS_check(_efs[index]->fs) != SPIFFS_OK) { | 
					
						
							|  |  |  |         int spiffs_res = SPIFFS_errno(_efs[index]->fs); | 
					
						
							|  |  |  |         ESP_LOGE(TAG, "SPIFFS_check failed (%d)", spiffs_res); | 
					
						
							|  |  |  |         errno = spiffs_res_to_errno(SPIFFS_errno(_efs[index]->fs)); | 
					
						
							|  |  |  |         SPIFFS_clearerr(_efs[index]->fs); | 
					
						
							|  |  |  |         return ESP_FAIL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return ESP_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  | esp_err_t esp_spiffs_format(const char* partition_label) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-01-28 23:37:31 +08:00
										 |  |  |     bool partition_was_mounted = false; | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     int index; | 
					
						
							| 
									
										
										
										
											2018-01-28 23:37:31 +08:00
										 |  |  |     /* If the partition is not mounted, need to create SPIFFS structures
 | 
					
						
							|  |  |  |      * and mount the partition, unmount, format, delete SPIFFS structures. | 
					
						
							|  |  |  |      * See SPIFFS wiki for the reason why. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     esp_err_t err = esp_spiffs_by_label(partition_label, &index); | 
					
						
							|  |  |  |     if (err != ESP_OK) { | 
					
						
							|  |  |  |         esp_vfs_spiffs_conf_t conf = { | 
					
						
							|  |  |  |                 .format_if_mount_failed = true, | 
					
						
							|  |  |  |                 .partition_label = partition_label, | 
					
						
							|  |  |  |                 .max_files = 1 | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         err = esp_spiffs_init(&conf); | 
					
						
							|  |  |  |         if (err != ESP_OK) { | 
					
						
							|  |  |  |             return err; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         err = esp_spiffs_by_label(partition_label, &index); | 
					
						
							| 
									
										
										
										
											2018-01-28 23:37:31 +08:00
										 |  |  |         assert(err == ESP_OK && "failed to get index of the partition just mounted"); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     } else if (SPIFFS_mounted(_efs[index]->fs)) { | 
					
						
							| 
									
										
										
										
											2018-01-28 23:37:31 +08:00
										 |  |  |         partition_was_mounted = true; | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-01-28 23:37:31 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     SPIFFS_unmount(_efs[index]->fs); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     s32_t res = SPIFFS_format(_efs[index]->fs); | 
					
						
							|  |  |  |     if (res != SPIFFS_OK) { | 
					
						
							| 
									
										
										
										
											2022-10-06 16:16:32 +02:00
										 |  |  |         ESP_LOGE(TAG, "format failed, %" PRId32, SPIFFS_errno(_efs[index]->fs)); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |         SPIFFS_clearerr(_efs[index]->fs); | 
					
						
							| 
									
										
										
										
											2018-01-28 23:37:31 +08:00
										 |  |  |         /* If the partition was previously mounted, but format failed, don't
 | 
					
						
							|  |  |  |          * try to mount the partition back (it will probably fail). On the | 
					
						
							|  |  |  |          * other hand, if it was not mounted, need to clean up. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if (!partition_was_mounted) { | 
					
						
							|  |  |  |             esp_spiffs_free(&_efs[index]); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |         return ESP_FAIL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-28 23:37:31 +08:00
										 |  |  |     if (partition_was_mounted) { | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |         res = SPIFFS_mount(_efs[index]->fs, &_efs[index]->cfg, _efs[index]->work, | 
					
						
							|  |  |  |                             _efs[index]->fds, _efs[index]->fds_sz, _efs[index]->cache, | 
					
						
							|  |  |  |                             _efs[index]->cache_sz, spiffs_api_check); | 
					
						
							|  |  |  |         if (res != SPIFFS_OK) { | 
					
						
							| 
									
										
										
										
											2022-10-06 16:16:32 +02:00
										 |  |  |             ESP_LOGE(TAG, "mount failed, %" PRId32, SPIFFS_errno(_efs[index]->fs)); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |             SPIFFS_clearerr(_efs[index]->fs); | 
					
						
							|  |  |  |             return ESP_FAIL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-01-28 23:37:31 +08:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         esp_spiffs_free(&_efs[index]); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     } | 
					
						
							|  |  |  |     return ESP_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 17:50:01 +01:00
										 |  |  | esp_err_t esp_spiffs_gc(const char* partition_label, size_t size_to_gc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int index; | 
					
						
							|  |  |  |     if (esp_spiffs_by_label(partition_label, &index) != ESP_OK) { | 
					
						
							|  |  |  |         return ESP_ERR_INVALID_STATE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     int res = SPIFFS_gc(_efs[index]->fs, size_to_gc); | 
					
						
							|  |  |  |     if (res != SPIFFS_OK) { | 
					
						
							|  |  |  |         ESP_LOGE(TAG, "SPIFFS_gc failed, %d", res); | 
					
						
							|  |  |  |         SPIFFS_clearerr(_efs[index]->fs); | 
					
						
							|  |  |  |         if (res == SPIFFS_ERR_FULL) { | 
					
						
							|  |  |  |             return ESP_ERR_NOT_FINISHED; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return ESP_FAIL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return ESP_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  | esp_err_t esp_vfs_spiffs_register(const esp_vfs_spiffs_conf_t * conf) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(conf->base_path); | 
					
						
							| 
									
										
										
										
											2023-07-17 11:59:28 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     esp_err_t err = esp_spiffs_init(conf); | 
					
						
							|  |  |  |     if (err != ESP_OK) { | 
					
						
							|  |  |  |         return err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int index; | 
					
						
							|  |  |  |     if (esp_spiffs_by_label(conf->partition_label, &index) != ESP_OK) { | 
					
						
							|  |  |  |         return ESP_ERR_INVALID_STATE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int vfs_flags = ESP_VFS_FLAG_CONTEXT_PTR; | 
					
						
							|  |  |  |     if (_efs[index]->partition->readonly) { | 
					
						
							|  |  |  |         vfs_flags |= ESP_VFS_FLAG_READONLY_FS; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     const esp_vfs_t vfs = { | 
					
						
							| 
									
										
										
										
											2023-07-17 11:59:28 +02:00
										 |  |  |         .flags = vfs_flags, | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |         .write_p = &vfs_spiffs_write, | 
					
						
							|  |  |  |         .lseek_p = &vfs_spiffs_lseek, | 
					
						
							|  |  |  |         .read_p = &vfs_spiffs_read, | 
					
						
							|  |  |  |         .open_p = &vfs_spiffs_open, | 
					
						
							|  |  |  |         .close_p = &vfs_spiffs_close, | 
					
						
							|  |  |  |         .fstat_p = &vfs_spiffs_fstat, | 
					
						
							| 
									
										
										
										
											2020-03-20 13:24:18 +01:00
										 |  |  | #ifdef CONFIG_VFS_SUPPORT_DIR
 | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |         .stat_p = &vfs_spiffs_stat, | 
					
						
							|  |  |  |         .link_p = &vfs_spiffs_link, | 
					
						
							|  |  |  |         .unlink_p = &vfs_spiffs_unlink, | 
					
						
							|  |  |  |         .rename_p = &vfs_spiffs_rename, | 
					
						
							|  |  |  |         .opendir_p = &vfs_spiffs_opendir, | 
					
						
							|  |  |  |         .closedir_p = &vfs_spiffs_closedir, | 
					
						
							|  |  |  |         .readdir_p = &vfs_spiffs_readdir, | 
					
						
							|  |  |  |         .readdir_r_p = &vfs_spiffs_readdir_r, | 
					
						
							|  |  |  |         .seekdir_p = &vfs_spiffs_seekdir, | 
					
						
							|  |  |  |         .telldir_p = &vfs_spiffs_telldir, | 
					
						
							|  |  |  |         .mkdir_p = &vfs_spiffs_mkdir, | 
					
						
							| 
									
										
										
										
											2018-10-25 11:53:52 +02:00
										 |  |  |         .rmdir_p = &vfs_spiffs_rmdir, | 
					
						
							| 
									
										
										
										
											2022-03-18 15:19:18 +05:30
										 |  |  |         .truncate_p = &vfs_spiffs_truncate, | 
					
						
							|  |  |  |         .ftruncate_p = &vfs_spiffs_ftruncate, | 
					
						
							| 
									
										
										
										
											2018-10-25 11:53:52 +02:00
										 |  |  | #ifdef CONFIG_SPIFFS_USE_MTIME
 | 
					
						
							|  |  |  |         .utime_p = &vfs_spiffs_utime, | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |         .utime_p = NULL, | 
					
						
							|  |  |  | #endif // CONFIG_SPIFFS_USE_MTIME
 | 
					
						
							| 
									
										
										
										
											2020-03-20 13:24:18 +01:00
										 |  |  | #endif // CONFIG_VFS_SUPPORT_DIR
 | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     strlcat(_efs[index]->base_path, conf->base_path, ESP_VFS_PATH_MAX + 1); | 
					
						
							|  |  |  |     err = esp_vfs_register(conf->base_path, &vfs, _efs[index]); | 
					
						
							|  |  |  |     if (err != ESP_OK) { | 
					
						
							|  |  |  |         esp_spiffs_free(&_efs[index]); | 
					
						
							|  |  |  |         return err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ESP_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | esp_err_t esp_vfs_spiffs_unregister(const char* partition_label) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int index; | 
					
						
							|  |  |  |     if (esp_spiffs_by_label(partition_label, &index) != ESP_OK) { | 
					
						
							|  |  |  |         return ESP_ERR_INVALID_STATE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     esp_err_t err = esp_vfs_unregister(_efs[index]->base_path); | 
					
						
							|  |  |  |     if (err != ESP_OK) { | 
					
						
							|  |  |  |         return err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     esp_spiffs_free(&_efs[index]); | 
					
						
							|  |  |  |     return ESP_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int spiffs_res_to_errno(s32_t fr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch(fr) { | 
					
						
							|  |  |  |     case SPIFFS_OK : | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     case SPIFFS_ERR_NOT_MOUNTED : | 
					
						
							|  |  |  |         return ENODEV; | 
					
						
							|  |  |  |     case SPIFFS_ERR_NOT_A_FS : | 
					
						
							|  |  |  |         return ENODEV; | 
					
						
							|  |  |  |     case SPIFFS_ERR_FULL : | 
					
						
							|  |  |  |         return ENOSPC; | 
					
						
							|  |  |  |     case SPIFFS_ERR_BAD_DESCRIPTOR : | 
					
						
							|  |  |  |         return EBADF; | 
					
						
							|  |  |  |     case SPIFFS_ERR_MOUNTED : | 
					
						
							|  |  |  |         return EEXIST; | 
					
						
							|  |  |  |     case SPIFFS_ERR_FILE_EXISTS : | 
					
						
							|  |  |  |         return EEXIST; | 
					
						
							|  |  |  |     case SPIFFS_ERR_NOT_FOUND : | 
					
						
							|  |  |  |         return ENOENT; | 
					
						
							|  |  |  |     case SPIFFS_ERR_NOT_A_FILE : | 
					
						
							|  |  |  |         return ENOENT; | 
					
						
							|  |  |  |     case SPIFFS_ERR_DELETED : | 
					
						
							|  |  |  |         return ENOENT; | 
					
						
							|  |  |  |     case SPIFFS_ERR_FILE_DELETED : | 
					
						
							|  |  |  |         return ENOENT; | 
					
						
							|  |  |  |     case SPIFFS_ERR_NAME_TOO_LONG : | 
					
						
							|  |  |  |         return ENAMETOOLONG; | 
					
						
							|  |  |  |     case SPIFFS_ERR_RO_NOT_IMPL : | 
					
						
							|  |  |  |         return EROFS; | 
					
						
							|  |  |  |     case SPIFFS_ERR_RO_ABORTED_OPERATION : | 
					
						
							|  |  |  |         return EROFS; | 
					
						
							|  |  |  |     default : | 
					
						
							|  |  |  |         return EIO; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return ENOTSUP; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int spiffs_mode_conv(int m) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int res = 0; | 
					
						
							|  |  |  |     int acc_mode = m & O_ACCMODE; | 
					
						
							|  |  |  |     if (acc_mode == O_RDONLY) { | 
					
						
							|  |  |  |         res |= SPIFFS_O_RDONLY; | 
					
						
							|  |  |  |     } else if (acc_mode == O_WRONLY) { | 
					
						
							|  |  |  |         res |= SPIFFS_O_WRONLY; | 
					
						
							|  |  |  |     } else if (acc_mode == O_RDWR) { | 
					
						
							|  |  |  |         res |= SPIFFS_O_RDWR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((m & O_CREAT) && (m & O_EXCL)) { | 
					
						
							|  |  |  |         res |= SPIFFS_O_CREAT | SPIFFS_O_EXCL; | 
					
						
							|  |  |  |     } else if ((m & O_CREAT) && (m & O_TRUNC)) { | 
					
						
							|  |  |  |         res |= SPIFFS_O_CREAT | SPIFFS_O_TRUNC; | 
					
						
							| 
									
										
										
										
											2018-05-10 14:26:47 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (m & O_APPEND) { | 
					
						
							| 
									
										
										
										
											2017-09-19 17:09:20 +08:00
										 |  |  |         res |= SPIFFS_O_CREAT | SPIFFS_O_APPEND; | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     } | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int vfs_spiffs_open(void* ctx, const char * path, int flags, int mode) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(path); | 
					
						
							|  |  |  |     esp_spiffs_t * efs = (esp_spiffs_t *)ctx; | 
					
						
							| 
									
										
										
										
											2017-11-22 00:17:11 +08:00
										 |  |  |     int spiffs_flags = spiffs_mode_conv(flags); | 
					
						
							|  |  |  |     int fd = SPIFFS_open(efs->fs, path, spiffs_flags, mode); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     if (fd < 0) { | 
					
						
							|  |  |  |         errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs)); | 
					
						
							|  |  |  |         SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-11-22 00:17:11 +08:00
										 |  |  |     if (!(spiffs_flags & SPIFFS_RDONLY)) { | 
					
						
							|  |  |  |         vfs_spiffs_update_mtime(efs->fs, fd); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     return fd; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t vfs_spiffs_write(void* ctx, int fd, const void * data, size_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     esp_spiffs_t * efs = (esp_spiffs_t *)ctx; | 
					
						
							|  |  |  |     ssize_t res = SPIFFS_write(efs->fs, fd, (void *)data, size); | 
					
						
							|  |  |  |     if (res < 0) { | 
					
						
							|  |  |  |         errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs)); | 
					
						
							|  |  |  |         SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t vfs_spiffs_read(void* ctx, int fd, void * dst, size_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     esp_spiffs_t * efs = (esp_spiffs_t *)ctx; | 
					
						
							|  |  |  |     ssize_t res = SPIFFS_read(efs->fs, fd, dst, size); | 
					
						
							|  |  |  |     if (res < 0) { | 
					
						
							|  |  |  |         errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs)); | 
					
						
							|  |  |  |         SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int vfs_spiffs_close(void* ctx, int fd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     esp_spiffs_t * efs = (esp_spiffs_t *)ctx; | 
					
						
							|  |  |  |     int res = SPIFFS_close(efs->fs, fd); | 
					
						
							|  |  |  |     if (res < 0) { | 
					
						
							|  |  |  |         errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs)); | 
					
						
							|  |  |  |         SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static off_t vfs_spiffs_lseek(void* ctx, int fd, off_t offset, int mode) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     esp_spiffs_t * efs = (esp_spiffs_t *)ctx; | 
					
						
							|  |  |  |     off_t res = SPIFFS_lseek(efs->fs, fd, offset, mode); | 
					
						
							|  |  |  |     if (res < 0) { | 
					
						
							|  |  |  |         errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs)); | 
					
						
							|  |  |  |         SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int vfs_spiffs_fstat(void* ctx, int fd, struct stat * st) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(st); | 
					
						
							|  |  |  |     spiffs_stat s; | 
					
						
							|  |  |  |     esp_spiffs_t * efs = (esp_spiffs_t *)ctx; | 
					
						
							|  |  |  |     off_t res = SPIFFS_fstat(efs->fs, fd, &s); | 
					
						
							|  |  |  |     if (res < 0) { | 
					
						
							|  |  |  |         errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs)); | 
					
						
							|  |  |  |         SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-11-05 17:38:22 +01:00
										 |  |  |     memset(st, 0, sizeof(*st)); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     st->st_size = s.size; | 
					
						
							|  |  |  |     st->st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFREG; | 
					
						
							| 
									
										
										
										
											2017-11-22 00:17:11 +08:00
										 |  |  |     st->st_mtime = vfs_spiffs_get_mtime(&s); | 
					
						
							| 
									
										
										
										
											2017-10-14 14:52:40 +02:00
										 |  |  |     st->st_atime = 0; | 
					
						
							|  |  |  |     st->st_ctime = 0; | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-20 13:24:18 +01:00
										 |  |  | #ifdef CONFIG_VFS_SUPPORT_DIR
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  | static int vfs_spiffs_stat(void* ctx, const char * path, struct stat * st) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(path); | 
					
						
							|  |  |  |     assert(st); | 
					
						
							|  |  |  |     spiffs_stat s; | 
					
						
							|  |  |  |     esp_spiffs_t * efs = (esp_spiffs_t *)ctx; | 
					
						
							|  |  |  |     off_t res = SPIFFS_stat(efs->fs, path, &s); | 
					
						
							|  |  |  |     if (res < 0) { | 
					
						
							|  |  |  |         errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs)); | 
					
						
							|  |  |  |         SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-11-05 17:38:22 +01:00
										 |  |  |     memset(st, 0, sizeof(*st)); | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     st->st_size = s.size; | 
					
						
							|  |  |  |     st->st_mode = S_IRWXU | S_IRWXG | S_IRWXO; | 
					
						
							|  |  |  |     st->st_mode |= (s.type == SPIFFS_TYPE_DIR)?S_IFDIR:S_IFREG; | 
					
						
							| 
									
										
										
										
											2017-11-22 00:17:11 +08:00
										 |  |  |     st->st_mtime = vfs_spiffs_get_mtime(&s); | 
					
						
							| 
									
										
										
										
											2017-10-14 14:52:40 +02:00
										 |  |  |     st->st_atime = 0; | 
					
						
							|  |  |  |     st->st_ctime = 0; | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int vfs_spiffs_rename(void* ctx, const char *src, const char *dst) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(src); | 
					
						
							|  |  |  |     assert(dst); | 
					
						
							|  |  |  |     esp_spiffs_t * efs = (esp_spiffs_t *)ctx; | 
					
						
							|  |  |  |     int res = SPIFFS_rename(efs->fs, src, dst); | 
					
						
							|  |  |  |     if (res < 0) { | 
					
						
							|  |  |  |         errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs)); | 
					
						
							|  |  |  |         SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int vfs_spiffs_unlink(void* ctx, const char *path) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(path); | 
					
						
							|  |  |  |     esp_spiffs_t * efs = (esp_spiffs_t *)ctx; | 
					
						
							|  |  |  |     int res = SPIFFS_remove(efs->fs, path); | 
					
						
							|  |  |  |     if (res < 0) { | 
					
						
							|  |  |  |         errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs)); | 
					
						
							|  |  |  |         SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static DIR* vfs_spiffs_opendir(void* ctx, const char* name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(name); | 
					
						
							|  |  |  |     esp_spiffs_t * efs = (esp_spiffs_t *)ctx; | 
					
						
							|  |  |  |     vfs_spiffs_dir_t * dir = calloc(1, sizeof(vfs_spiffs_dir_t)); | 
					
						
							|  |  |  |     if (!dir) { | 
					
						
							|  |  |  |         errno = ENOMEM; | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!SPIFFS_opendir(efs->fs, name, &dir->d)) { | 
					
						
							|  |  |  |         free(dir); | 
					
						
							|  |  |  |         errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs)); | 
					
						
							|  |  |  |         SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     dir->offset = 0; | 
					
						
							|  |  |  |     strlcpy(dir->path, name, SPIFFS_OBJ_NAME_LEN); | 
					
						
							|  |  |  |     return (DIR*) dir; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int vfs_spiffs_closedir(void* ctx, DIR* pdir) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(pdir); | 
					
						
							|  |  |  |     esp_spiffs_t * efs = (esp_spiffs_t *)ctx; | 
					
						
							|  |  |  |     vfs_spiffs_dir_t * dir = (vfs_spiffs_dir_t *)pdir; | 
					
						
							|  |  |  |     int res = SPIFFS_closedir(&dir->d); | 
					
						
							|  |  |  |     free(dir); | 
					
						
							|  |  |  |     if (res < 0) { | 
					
						
							|  |  |  |         errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs)); | 
					
						
							|  |  |  |         SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct dirent* vfs_spiffs_readdir(void* ctx, DIR* pdir) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(pdir); | 
					
						
							|  |  |  |     vfs_spiffs_dir_t * dir = (vfs_spiffs_dir_t *)pdir; | 
					
						
							|  |  |  |     struct dirent* out_dirent; | 
					
						
							|  |  |  |     int err = vfs_spiffs_readdir_r(ctx, pdir, &dir->e, &out_dirent); | 
					
						
							|  |  |  |     if (err != 0) { | 
					
						
							|  |  |  |         errno = err; | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return out_dirent; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-22 16:47:30 +08:00
										 |  |  | static int vfs_spiffs_readdir_r(void* ctx, DIR* pdir, struct dirent* entry, | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |                                 struct dirent** out_dirent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(pdir); | 
					
						
							|  |  |  |     esp_spiffs_t * efs = (esp_spiffs_t *)ctx; | 
					
						
							|  |  |  |     vfs_spiffs_dir_t * dir = (vfs_spiffs_dir_t *)pdir; | 
					
						
							|  |  |  |     struct spiffs_dirent out; | 
					
						
							| 
									
										
										
										
											2018-07-20 10:27:53 -04:00
										 |  |  |     size_t plen; | 
					
						
							|  |  |  |     char * item_name; | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |         if (SPIFFS_readdir(&dir->d, &out) == 0) { | 
					
						
							|  |  |  |             errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs)); | 
					
						
							|  |  |  |             SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |             if (!errno) { | 
					
						
							|  |  |  |                 *out_dirent = NULL; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return errno; | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-07-20 10:27:53 -04:00
										 |  |  |         item_name = (char *)out.name; | 
					
						
							|  |  |  |         plen = strlen(dir->path); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } while ((plen > 1) && (strncasecmp(dir->path, (const char*)out.name, plen) || out.name[plen] != '/' || !out.name[plen + 1])); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     if (plen > 1) { | 
					
						
							|  |  |  |         item_name += plen + 1; | 
					
						
							|  |  |  |     } else if (item_name[0] == '/') { | 
					
						
							|  |  |  |         item_name++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     entry->d_ino = 0; | 
					
						
							|  |  |  |     entry->d_type = out.type; | 
					
						
							| 
									
										
										
										
											2022-02-22 18:05:49 +07:00
										 |  |  |     strncpy(entry->d_name, item_name, SPIFFS_OBJ_NAME_LEN); | 
					
						
							|  |  |  |     entry->d_name[SPIFFS_OBJ_NAME_LEN - 1] = '\0'; | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  |     dir->offset++; | 
					
						
							|  |  |  |     *out_dirent = entry; | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static long vfs_spiffs_telldir(void* ctx, DIR* pdir) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(pdir); | 
					
						
							|  |  |  |     vfs_spiffs_dir_t * dir = (vfs_spiffs_dir_t *)pdir; | 
					
						
							|  |  |  |     return dir->offset; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void vfs_spiffs_seekdir(void* ctx, DIR* pdir, long offset) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(pdir); | 
					
						
							|  |  |  |     esp_spiffs_t * efs = (esp_spiffs_t *)ctx; | 
					
						
							|  |  |  |     vfs_spiffs_dir_t * dir = (vfs_spiffs_dir_t *)pdir; | 
					
						
							|  |  |  |     struct spiffs_dirent tmp; | 
					
						
							|  |  |  |     if (offset < dir->offset) { | 
					
						
							|  |  |  |         //rewind dir
 | 
					
						
							|  |  |  |         SPIFFS_closedir(&dir->d); | 
					
						
							|  |  |  |         if (!SPIFFS_opendir(efs->fs, NULL, &dir->d)) { | 
					
						
							|  |  |  |             errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs)); | 
					
						
							|  |  |  |             SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         dir->offset = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     while (dir->offset < offset) { | 
					
						
							|  |  |  |         if (SPIFFS_readdir(&dir->d, &tmp) == 0) { | 
					
						
							|  |  |  |             errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs)); | 
					
						
							|  |  |  |             SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         size_t plen = strlen(dir->path); | 
					
						
							|  |  |  |         if (plen > 1) { | 
					
						
							|  |  |  |             if (strncasecmp(dir->path, (const char *)tmp.name, plen) || tmp.name[plen] != '/' || !tmp.name[plen+1]) { | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         dir->offset++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int vfs_spiffs_mkdir(void* ctx, const char* name, mode_t mode) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     errno = ENOTSUP; | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int vfs_spiffs_rmdir(void* ctx, const char* name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     errno = ENOTSUP; | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-18 15:19:18 +05:30
										 |  |  | static int vfs_spiffs_truncate(void* ctx, const char *path, off_t length) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(path); | 
					
						
							|  |  |  |     esp_spiffs_t * efs = (esp_spiffs_t *)ctx; | 
					
						
							|  |  |  |     int fd = SPIFFS_open(efs->fs, path, SPIFFS_WRONLY, 0); | 
					
						
							|  |  |  |     if (fd < 0) { | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int res = SPIFFS_ftruncate(efs->fs, fd, length); | 
					
						
							|  |  |  |     if (res < 0) { | 
					
						
							|  |  |  |         (void)SPIFFS_close(efs->fs, fd); | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     res = SPIFFS_close(efs->fs, fd); | 
					
						
							|  |  |  |     if (res < 0) { | 
					
						
							|  |  |  |        goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  | err: | 
					
						
							|  |  |  |     errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs)); | 
					
						
							|  |  |  |     SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int vfs_spiffs_ftruncate(void* ctx, int fd, off_t length) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     esp_spiffs_t * efs = (esp_spiffs_t *)ctx; | 
					
						
							|  |  |  |     int res = SPIFFS_ftruncate(efs->fs, fd, length); | 
					
						
							|  |  |  |     if (res < 0) { | 
					
						
							|  |  |  |         errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs)); | 
					
						
							|  |  |  |         SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-07 17:37:59 +03:00
										 |  |  | static int vfs_spiffs_link(void* ctx, const char* n1, const char* n2) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     errno = ENOTSUP; | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-11-22 00:17:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-25 11:53:52 +02:00
										 |  |  | #ifdef CONFIG_SPIFFS_USE_MTIME
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:58:54 +08:00
										 |  |  | static int vfs_spiffs_update_mtime_value(spiffs *fs, const char *path, spiffs_time_t t) | 
					
						
							| 
									
										
										
										
											2018-10-25 11:53:52 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     int ret = SPIFFS_OK; | 
					
						
							|  |  |  |     spiffs_stat s; | 
					
						
							|  |  |  |     if (CONFIG_SPIFFS_META_LENGTH > sizeof(t)) { | 
					
						
							|  |  |  |         ret = SPIFFS_stat(fs, path, &s); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (ret == SPIFFS_OK) { | 
					
						
							|  |  |  |         memcpy(s.meta, &t, sizeof(t)); | 
					
						
							|  |  |  |         ret = SPIFFS_update_meta(fs, path, s.meta); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (ret != SPIFFS_OK) { | 
					
						
							|  |  |  |         ESP_LOGW(TAG, "Failed to update mtime (%d)", ret); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif //CONFIG_SPIFFS_USE_MTIME
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_SPIFFS_USE_MTIME
 | 
					
						
							|  |  |  | static int vfs_spiffs_utime(void *ctx, const char *path, const struct utimbuf *times) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(path); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     esp_spiffs_t *efs = (esp_spiffs_t *) ctx; | 
					
						
							| 
									
										
										
										
											2020-01-10 12:58:54 +08:00
										 |  |  |     spiffs_time_t t; | 
					
						
							| 
									
										
										
										
											2018-10-25 11:53:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (times) { | 
					
						
							| 
									
										
										
										
											2020-01-10 12:58:54 +08:00
										 |  |  |         t = (spiffs_time_t)times->modtime; | 
					
						
							| 
									
										
										
										
											2018-10-25 11:53:52 +02:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         // use current time
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:58:54 +08:00
										 |  |  |         t = (spiffs_time_t)time(NULL); | 
					
						
							| 
									
										
										
										
											2018-10-25 11:53:52 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int ret = vfs_spiffs_update_mtime_value(efs->fs, path, t); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (ret != SPIFFS_OK) { | 
					
						
							|  |  |  |         errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs)); | 
					
						
							|  |  |  |         SPIFFS_clearerr(efs->fs); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif //CONFIG_SPIFFS_USE_MTIME
 | 
					
						
							| 
									
										
										
										
											2020-03-20 13:24:18 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #endif // CONFIG_VFS_SUPPORT_DIR
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void vfs_spiffs_update_mtime(spiffs *fs, spiffs_file fd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifdef CONFIG_SPIFFS_USE_MTIME
 | 
					
						
							|  |  |  |     spiffs_time_t t = (spiffs_time_t)time(NULL); | 
					
						
							|  |  |  |     spiffs_stat s; | 
					
						
							|  |  |  |     int ret = SPIFFS_OK; | 
					
						
							|  |  |  |     if (CONFIG_SPIFFS_META_LENGTH > sizeof(t)) { | 
					
						
							|  |  |  |         ret = SPIFFS_fstat(fs, fd, &s); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (ret == SPIFFS_OK) { | 
					
						
							|  |  |  |         memcpy(s.meta, &t, sizeof(t)); | 
					
						
							|  |  |  |         ret = SPIFFS_fupdate_meta(fs, fd, s.meta); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (ret != SPIFFS_OK) { | 
					
						
							|  |  |  |         ESP_LOGW(TAG, "Failed to update mtime (%d)", ret); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif //CONFIG_SPIFFS_USE_MTIME
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static time_t vfs_spiffs_get_mtime(const spiffs_stat* s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifdef CONFIG_SPIFFS_USE_MTIME
 | 
					
						
							|  |  |  |     spiffs_time_t t = 0; | 
					
						
							|  |  |  |     memcpy(&t, s->meta, sizeof(t)); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |     time_t t = 0; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     return (time_t)t; | 
					
						
							|  |  |  | } |