Commit 4f1b33d5 authored by Johny Mattsson's avatar Johny Mattsson
Browse files

Grabbed latest spiffs + vfs layer from dev branch.

Also included the recent LVM fix.

Platform flash layer not yet functional.
parent fe602d2d
#include "spiffs.h" #include "spiffs.h"
#include "spiffs_nucleus.h" #include "spiffs_nucleus.h"
#include <string.h>
#if !SPIFFS_READ_ONLY
// Erases a logical block and updates the erase counter. // Erases a logical block and updates the erase counter.
// If cache is enabled, all pages that might be cached in this block // If cache is enabled, all pages that might be cached in this block
...@@ -36,7 +39,7 @@ s32_t spiffs_gc_quick( ...@@ -36,7 +39,7 @@ s32_t spiffs_gc_quick(
int cur_entry = 0; int cur_entry = 0;
spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work; spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
SPIFFS_GC_DBG("gc_quick: running\n", cur_block); SPIFFS_GC_DBG("gc_quick: running\n");
#if SPIFFS_GC_STATS #if SPIFFS_GC_STATS
fs->stats_gc_runs++; fs->stats_gc_runs++;
#endif #endif
...@@ -249,14 +252,12 @@ s32_t spiffs_gc_find_candidate( ...@@ -249,14 +252,12 @@ s32_t spiffs_gc_find_candidate(
memset(fs->work, 0xff, SPIFFS_CFG_LOG_PAGE_SZ(fs)); memset(fs->work, 0xff, SPIFFS_CFG_LOG_PAGE_SZ(fs));
// divide up work area into block indices and scores // divide up work area into block indices and scores
// todo alignment?
// YES DO PROPER ALIGNMENT !^@#%!@%!
if (max_candidates & 1)
++max_candidates; // HACK WORKAROUND ICK for sizeof(spiffs_block_idx)==2
spiffs_block_ix *cand_blocks = (spiffs_block_ix *)fs->work; spiffs_block_ix *cand_blocks = (spiffs_block_ix *)fs->work;
s32_t *cand_scores = (s32_t *)(fs->work + max_candidates * sizeof(spiffs_block_ix)); s32_t *cand_scores = (s32_t *)(fs->work + max_candidates * sizeof(spiffs_block_ix));
// align cand_scores on s32_t boundary
cand_scores = (s32_t*)(((ptrdiff_t)cand_scores + sizeof(ptrdiff_t) - 1) & ~(sizeof(ptrdiff_t) - 1));
*block_candidates = cand_blocks; *block_candidates = cand_blocks;
int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id)); int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
...@@ -570,3 +571,4 @@ s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) { ...@@ -570,3 +571,4 @@ s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
return res; return res;
} }
#endif // !SPIFFS_READ_ONLY
...@@ -7,8 +7,19 @@ ...@@ -7,8 +7,19 @@
#include "spiffs.h" #include "spiffs.h"
#include "spiffs_nucleus.h" #include "spiffs_nucleus.h"
#include <string.h>
#if SPIFFS_FILEHDL_OFFSET
#define SPIFFS_FH_OFFS(fs, fh) ((fh) != 0 ? ((fh) + (fs)->cfg.fh_ix_offset) : 0)
#define SPIFFS_FH_UNOFFS(fs, fh) ((fh) != 0 ? ((fh) - (fs)->cfg.fh_ix_offset) : 0)
#else
#define SPIFFS_FH_OFFS(fs, fh) (fh)
#define SPIFFS_FH_UNOFFS(fs, fh) (fh)
#endif
#if SPIFFS_CACHE == 1
static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh); static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh);
#endif
#if SPIFFS_BUFFER_HELP #if SPIFFS_BUFFER_HELP
u32_t SPIFFS_buffer_bytes_for_filedescs(spiffs *fs, u32_t num_descs) { u32_t SPIFFS_buffer_bytes_for_filedescs(spiffs *fs, u32_t num_descs) {
...@@ -26,6 +37,10 @@ u8_t SPIFFS_mounted(spiffs *fs) { ...@@ -26,6 +37,10 @@ u8_t SPIFFS_mounted(spiffs *fs) {
} }
s32_t SPIFFS_format(spiffs *fs) { s32_t SPIFFS_format(spiffs *fs) {
#if SPIFFS_READ_ONLY
(void)fs;
return SPIFFS_ERR_RO_NOT_IMPL;
#else
SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_CFG(fs);
if (SPIFFS_CHECK_MOUNT(fs)) { if (SPIFFS_CHECK_MOUNT(fs)) {
fs->err_code = SPIFFS_ERR_MOUNTED; fs->err_code = SPIFFS_ERR_MOUNTED;
...@@ -49,25 +64,35 @@ s32_t SPIFFS_format(spiffs *fs) { ...@@ -49,25 +64,35 @@ s32_t SPIFFS_format(spiffs *fs) {
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return 0; return 0;
#endif // SPIFFS_READ_ONLY
} }
#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
s32_t SPIFFS_probe_fs(spiffs_config *config) {
s32_t res = spiffs_probe(config);
return res;
}
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work, s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
u8_t *fd_space, u32_t fd_space_size, u8_t *fd_space, u32_t fd_space_size,
void *cache, u32_t cache_size, void *cache, u32_t cache_size,
spiffs_check_callback check_cb_f) { spiffs_check_callback check_cb_f) {
void *user_data;
SPIFFS_LOCK(fs); SPIFFS_LOCK(fs);
user_data = fs->user_data;
memset(fs, 0, sizeof(spiffs)); memset(fs, 0, sizeof(spiffs));
memcpy(&fs->cfg, config, sizeof(spiffs_config)); memcpy(&fs->cfg, config, sizeof(spiffs_config));
fs->user_data = user_data;
fs->block_count = SPIFFS_CFG_PHYS_SZ(fs) / SPIFFS_CFG_LOG_BLOCK_SZ(fs); fs->block_count = SPIFFS_CFG_PHYS_SZ(fs) / SPIFFS_CFG_LOG_BLOCK_SZ(fs);
fs->work = &work[0]; fs->work = &work[0];
fs->lu_work = &work[SPIFFS_CFG_LOG_PAGE_SZ(fs)]; fs->lu_work = &work[SPIFFS_CFG_LOG_PAGE_SZ(fs)];
memset(fd_space, 0, fd_space_size); memset(fd_space, 0, fd_space_size);
// align fd_space pointer to pointer size byte boundary, below is safe // align fd_space pointer to pointer size byte boundary
u8_t ptr_size = sizeof(void*); u8_t ptr_size = sizeof(void*);
#pragma GCC diagnostic push u8_t addr_lsb = ((u8_t)(intptr_t)fd_space) & (ptr_size-1);
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
u8_t addr_lsb = ((u8_t)fd_space) & (ptr_size-1);
#pragma GCC diagnostic pop
if (addr_lsb) { if (addr_lsb) {
fd_space += (ptr_size-addr_lsb); fd_space += (ptr_size-addr_lsb);
fd_space_size -= (ptr_size-addr_lsb); fd_space_size -= (ptr_size-addr_lsb);
...@@ -75,11 +100,8 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work, ...@@ -75,11 +100,8 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
fs->fd_space = fd_space; fs->fd_space = fd_space;
fs->fd_count = (fd_space_size/sizeof(spiffs_fd)); fs->fd_count = (fd_space_size/sizeof(spiffs_fd));
// align cache pointer to 4 byte boundary, below is safe // align cache pointer to 4 byte boundary
#pragma GCC diagnostic push addr_lsb = ((u8_t)(intptr_t)cache) & (ptr_size-1);
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
addr_lsb = ((u8_t)cache) & (ptr_size-1);
#pragma GCC diagnostic pop
if (addr_lsb) { if (addr_lsb) {
u8_t *cache_8 = (u8_t *)cache; u8_t *cache_8 = (u8_t *)cache;
cache_8 += (ptr_size-addr_lsb); cache_8 += (ptr_size-addr_lsb);
...@@ -89,9 +111,10 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work, ...@@ -89,9 +111,10 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
if (cache_size & (ptr_size-1)) { if (cache_size & (ptr_size-1)) {
cache_size -= (cache_size & (ptr_size-1)); cache_size -= (cache_size & (ptr_size-1));
} }
#if SPIFFS_CACHE #if SPIFFS_CACHE
fs->cache = cache; fs->cache = cache;
fs->cache_size = (cache_size > (config->log_page_size*32)) ? config->log_page_size*32 : cache_size; fs->cache_size = (cache_size > (SPIFFS_CFG_LOG_PAGE_SZ(fs)*32)) ? SPIFFS_CFG_LOG_PAGE_SZ(fs)*32 : cache_size;
spiffs_cache_init(fs); spiffs_cache_init(fs);
#endif #endif
...@@ -152,43 +175,68 @@ void SPIFFS_clearerr(spiffs *fs) { ...@@ -152,43 +175,68 @@ void SPIFFS_clearerr(spiffs *fs) {
fs->err_code = SPIFFS_OK; fs->err_code = SPIFFS_OK;
} }
s32_t SPIFFS_creat(spiffs *fs, char *path, spiffs_mode mode) { s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode) {
#if SPIFFS_READ_ONLY
(void)fs; (void)path; (void)mode;
return SPIFFS_ERR_RO_NOT_IMPL;
#else
(void)mode; (void)mode;
SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_API_CHECK_MOUNT(fs);
if (strlen(path) > SPIFFS_OBJ_NAME_LEN - 1) {
SPIFFS_API_CHECK_RES(fs, SPIFFS_ERR_NAME_TOO_LONG);
}
SPIFFS_LOCK(fs); SPIFFS_LOCK(fs);
spiffs_obj_id obj_id; spiffs_obj_id obj_id;
s32_t res; s32_t res;
res = spiffs_obj_lu_find_free_obj_id(fs, &obj_id, (u8_t *)path); res = spiffs_obj_lu_find_free_obj_id(fs, &obj_id, (const u8_t*)path);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
res = spiffs_object_create(fs, obj_id, (u8_t *)path, SPIFFS_TYPE_FILE, 0); res = spiffs_object_create(fs, obj_id, (const u8_t*)path, SPIFFS_TYPE_FILE, 0);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return 0; return 0;
#endif // SPIFFS_READ_ONLY
} }
spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode mode) { spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs_mode mode) {
(void)mode; (void)mode;
SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_API_CHECK_MOUNT(fs);
if (strlen(path) > SPIFFS_OBJ_NAME_LEN - 1) {
SPIFFS_API_CHECK_RES(fs, SPIFFS_ERR_NAME_TOO_LONG);
}
SPIFFS_LOCK(fs); SPIFFS_LOCK(fs);
spiffs_fd *fd; spiffs_fd *fd;
spiffs_page_ix pix; spiffs_page_ix pix;
#if SPIFFS_READ_ONLY
// not valid flags in read only mode
flags &= ~SPIFFS_WRONLY | SPIFFS_CREAT | SPIFFS_TRUNC;
#endif // SPIFFS_READ_ONLY
s32_t res = spiffs_fd_find_new(fs, &fd); s32_t res = spiffs_fd_find_new(fs, &fd);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)path, &pix); res = spiffs_object_find_object_index_header_by_name(fs, (const u8_t*)path, &pix);
if ((flags & SPIFFS_CREAT) == 0) { if ((flags & SPIFFS_O_CREAT) == 0) {
if (res < SPIFFS_OK) { if (res < SPIFFS_OK) {
spiffs_fd_return(fs, fd->file_nbr); spiffs_fd_return(fs, fd->file_nbr);
} }
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
} }
if ((flags & SPIFFS_CREAT) && res == SPIFFS_ERR_NOT_FOUND) { if (res == SPIFFS_OK &&
(flags & (SPIFFS_O_CREAT | SPIFFS_O_EXCL)) == (SPIFFS_O_CREAT | SPIFFS_O_EXCL)) {
// creat and excl and file exists - fail
res = SPIFFS_ERR_FILE_EXISTS;
spiffs_fd_return(fs, fd->file_nbr);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
}
if ((flags & SPIFFS_O_CREAT) && res == SPIFFS_ERR_NOT_FOUND) {
#if !SPIFFS_READ_ONLY
spiffs_obj_id obj_id; spiffs_obj_id obj_id;
// no need to enter conflicting name here, already looked for it above // no need to enter conflicting name here, already looked for it above
res = spiffs_obj_lu_find_free_obj_id(fs, &obj_id, 0); res = spiffs_obj_lu_find_free_obj_id(fs, &obj_id, 0);
...@@ -196,12 +244,13 @@ spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode ...@@ -196,12 +244,13 @@ spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode
spiffs_fd_return(fs, fd->file_nbr); spiffs_fd_return(fs, fd->file_nbr);
} }
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
res = spiffs_object_create(fs, obj_id, (u8_t*)path, SPIFFS_TYPE_FILE, &pix); res = spiffs_object_create(fs, obj_id, (const u8_t*)path, SPIFFS_TYPE_FILE, &pix);
if (res < SPIFFS_OK) { if (res < SPIFFS_OK) {
spiffs_fd_return(fs, fd->file_nbr); spiffs_fd_return(fs, fd->file_nbr);
} }
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
flags &= ~SPIFFS_TRUNC; flags &= ~SPIFFS_O_TRUNC;
#endif // !SPIFFS_READ_ONLY
} else { } else {
if (res < SPIFFS_OK) { if (res < SPIFFS_OK) {
spiffs_fd_return(fs, fd->file_nbr); spiffs_fd_return(fs, fd->file_nbr);
...@@ -213,19 +262,21 @@ spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode ...@@ -213,19 +262,21 @@ spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode
spiffs_fd_return(fs, fd->file_nbr); spiffs_fd_return(fs, fd->file_nbr);
} }
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
if (flags & SPIFFS_TRUNC) { #if !SPIFFS_READ_ONLY
if (flags & SPIFFS_O_TRUNC) {
res = spiffs_object_truncate(fd, 0, 0); res = spiffs_object_truncate(fd, 0, 0);
if (res < SPIFFS_OK) { if (res < SPIFFS_OK) {
spiffs_fd_return(fs, fd->file_nbr); spiffs_fd_return(fs, fd->file_nbr);
} }
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
} }
#endif // !SPIFFS_READ_ONLY
fd->fdoffset = 0; fd->fdoffset = 0;
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return fd->file_nbr; return SPIFFS_FH_OFFS(fs, fd->file_nbr);
} }
spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_flags flags, spiffs_mode mode) { spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_flags flags, spiffs_mode mode) {
...@@ -243,19 +294,67 @@ spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_fl ...@@ -243,19 +294,67 @@ spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_fl
spiffs_fd_return(fs, fd->file_nbr); spiffs_fd_return(fs, fd->file_nbr);
} }
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
if (flags & SPIFFS_TRUNC) { #if !SPIFFS_READ_ONLY
if (flags & SPIFFS_O_TRUNC) {
res = spiffs_object_truncate(fd, 0, 0); res = spiffs_object_truncate(fd, 0, 0);
if (res < SPIFFS_OK) { if (res < SPIFFS_OK) {
spiffs_fd_return(fs, fd->file_nbr); spiffs_fd_return(fs, fd->file_nbr);
} }
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
} }
#endif // !SPIFFS_READ_ONLY
fd->fdoffset = 0; fd->fdoffset = 0;
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return fd->file_nbr; return SPIFFS_FH_OFFS(fs, fd->file_nbr);
}
spiffs_file SPIFFS_open_by_page(spiffs *fs, spiffs_page_ix page_ix, spiffs_flags flags, spiffs_mode mode) {
SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs);
SPIFFS_LOCK(fs);
spiffs_fd *fd;
s32_t res = spiffs_fd_find_new(fs, &fd);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
if (SPIFFS_IS_LOOKUP_PAGE(fs, page_ix)) {
res = SPIFFS_ERR_NOT_A_FILE;
spiffs_fd_return(fs, fd->file_nbr);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
}
res = spiffs_object_open_by_page(fs, page_ix, fd, flags, mode);
if (res == SPIFFS_ERR_IS_FREE ||
res == SPIFFS_ERR_DELETED ||
res == SPIFFS_ERR_NOT_FINALIZED ||
res == SPIFFS_ERR_NOT_INDEX ||
res == SPIFFS_ERR_INDEX_SPAN_MISMATCH) {
res = SPIFFS_ERR_NOT_A_FILE;
}
if (res < SPIFFS_OK) {
spiffs_fd_return(fs, fd->file_nbr);
}
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
#if !SPIFFS_READ_ONLY
if (flags & SPIFFS_O_TRUNC) {
res = spiffs_object_truncate(fd, 0, 0);
if (res < SPIFFS_OK) {
spiffs_fd_return(fs, fd->file_nbr);
}
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
}
#endif // !SPIFFS_READ_ONLY
fd->fdoffset = 0;
SPIFFS_UNLOCK(fs);
return SPIFFS_FH_OFFS(fs, fd->file_nbr);
} }
s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) { s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
...@@ -266,14 +365,21 @@ s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) { ...@@ -266,14 +365,21 @@ s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
spiffs_fd *fd; spiffs_fd *fd;
s32_t res; s32_t res;
fh = SPIFFS_FH_UNOFFS(fs, fh);
res = spiffs_fd_get(fs, fh, &fd); res = spiffs_fd_get(fs, fh, &fd);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
if ((fd->flags & SPIFFS_RDONLY) == 0) { if ((fd->flags & SPIFFS_O_RDONLY) == 0) {
res = SPIFFS_ERR_NOT_READABLE; res = SPIFFS_ERR_NOT_READABLE;
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
} }
if (fd->size == SPIFFS_UNDEFINED_LEN && len > 0) {
// special case for zero sized files
res = SPIFFS_ERR_END_OF_OBJECT;
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
}
#if SPIFFS_CACHE_WR #if SPIFFS_CACHE_WR
spiffs_fflush_cache(fs, fh); spiffs_fflush_cache(fs, fh);
#endif #endif
...@@ -305,6 +411,7 @@ s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) { ...@@ -305,6 +411,7 @@ s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
return len; return len;
} }
#if !SPIFFS_READ_ONLY
static s32_t spiffs_hydro_write(spiffs *fs, spiffs_fd *fd, void *buf, u32_t offset, s32_t len) { static s32_t spiffs_hydro_write(spiffs *fs, spiffs_fd *fd, void *buf, u32_t offset, s32_t len) {
(void)fs; (void)fs;
s32_t res = SPIFFS_OK; s32_t res = SPIFFS_OK;
...@@ -326,8 +433,13 @@ static s32_t spiffs_hydro_write(spiffs *fs, spiffs_fd *fd, void *buf, u32_t offs ...@@ -326,8 +433,13 @@ static s32_t spiffs_hydro_write(spiffs *fs, spiffs_fd *fd, void *buf, u32_t offs
return len; return len;
} }
#endif // !SPIFFS_READ_ONLY
s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) { s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
#if SPIFFS_READ_ONLY
(void)fs; (void)fh; (void)buf; (void)len;
return SPIFFS_ERR_RO_NOT_IMPL;
#else
SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_API_CHECK_MOUNT(fs);
SPIFFS_LOCK(fs); SPIFFS_LOCK(fs);
...@@ -336,14 +448,19 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) { ...@@ -336,14 +448,19 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
s32_t res; s32_t res;
u32_t offset; u32_t offset;
fh = SPIFFS_FH_UNOFFS(fs, fh);
res = spiffs_fd_get(fs, fh, &fd); res = spiffs_fd_get(fs, fh, &fd);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
if ((fd->flags & SPIFFS_WRONLY) == 0) { if ((fd->flags & SPIFFS_O_WRONLY) == 0) {
res = SPIFFS_ERR_NOT_WRITABLE; res = SPIFFS_ERR_NOT_WRITABLE;
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
} }
if ((fd->flags & SPIFFS_O_APPEND)) {
fd->fdoffset = fd->size == SPIFFS_UNDEFINED_LEN ? 0 : fd->size;
}
offset = fd->fdoffset; offset = fd->fdoffset;
#if SPIFFS_CACHE_WR #if SPIFFS_CACHE_WR
...@@ -352,7 +469,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) { ...@@ -352,7 +469,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
fd->cache_page = spiffs_cache_page_get_by_fd(fs, fd); fd->cache_page = spiffs_cache_page_get_by_fd(fs, fd);
} }
#endif #endif
if (fd->flags & SPIFFS_APPEND) { if (fd->flags & SPIFFS_O_APPEND) {
if (fd->size == SPIFFS_UNDEFINED_LEN) { if (fd->size == SPIFFS_UNDEFINED_LEN) {
offset = 0; offset = 0;
} else { } else {
...@@ -366,7 +483,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) { ...@@ -366,7 +483,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
} }
#if SPIFFS_CACHE_WR #if SPIFFS_CACHE_WR
if ((fd->flags & SPIFFS_DIRECT) == 0) { if ((fd->flags & SPIFFS_O_DIRECT) == 0) {
if (len < (s32_t)SPIFFS_CFG_LOG_PAGE_SZ(fs)) { if (len < (s32_t)SPIFFS_CFG_LOG_PAGE_SZ(fs)) {
// small write, try to cache it // small write, try to cache it
u8_t alloc_cpage = 1; u8_t alloc_cpage = 1;
...@@ -383,7 +500,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) { ...@@ -383,7 +500,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix), spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
fd->cache_page->offset, fd->cache_page->size); fd->cache_page->offset, fd->cache_page->size);
spiffs_cache_fd_release(fs, fd->cache_page); spiffs_cache_fd_release(fs, fd->cache_page);
SPIFFS_API_CHECK_RES(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
} else { } else {
// writing within cache // writing within cache
alloc_cpage = 0; alloc_cpage = 0;
...@@ -414,7 +531,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) { ...@@ -414,7 +531,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
return len; return len;
} else { } else {
res = spiffs_hydro_write(fs, fd, buf, offset, len); res = spiffs_hydro_write(fs, fd, buf, offset, len);
SPIFFS_API_CHECK_RES(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
fd->fdoffset += len; fd->fdoffset += len;
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return res; return res;
...@@ -429,21 +546,22 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) { ...@@ -429,21 +546,22 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix), spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
fd->cache_page->offset, fd->cache_page->size); fd->cache_page->offset, fd->cache_page->size);
spiffs_cache_fd_release(fs, fd->cache_page); spiffs_cache_fd_release(fs, fd->cache_page);
SPIFFS_API_CHECK_RES(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
res = spiffs_hydro_write(fs, fd, buf, offset, len); res = spiffs_hydro_write(fs, fd, buf, offset, len);
SPIFFS_API_CHECK_RES(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
} }
} }
} }
#endif #endif
res = spiffs_hydro_write(fs, fd, buf, offset, len); res = spiffs_hydro_write(fs, fd, buf, offset, len);
SPIFFS_API_CHECK_RES(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
fd->fdoffset += len; fd->fdoffset += len;
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return res; return res;
#endif // SPIFFS_READ_ONLY
} }
s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) { s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
...@@ -453,8 +571,9 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) { ...@@ -453,8 +571,9 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
spiffs_fd *fd; spiffs_fd *fd;
s32_t res; s32_t res;
fh = SPIFFS_FH_UNOFFS(fs, fh);
res = spiffs_fd_get(fs, fh, &fd); res = spiffs_fd_get(fs, fh, &fd);
SPIFFS_API_CHECK_RES(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
#if SPIFFS_CACHE_WR #if SPIFFS_CACHE_WR
spiffs_fflush_cache(fs, fh); spiffs_fflush_cache(fs, fh);
...@@ -469,7 +588,7 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) { ...@@ -469,7 +588,7 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
break; break;
} }
if (offs > (s32_t)fd->size) { if ((offs > (s32_t)fd->size) && (SPIFFS_UNDEFINED_LEN != fd->size)) {
res = SPIFFS_ERR_END_OF_OBJECT; res = SPIFFS_ERR_END_OF_OBJECT;
} }
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
...@@ -491,9 +610,16 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) { ...@@ -491,9 +610,16 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
return offs; return offs;
} }
s32_t SPIFFS_remove(spiffs *fs, char *path) { s32_t SPIFFS_remove(spiffs *fs, const char *path) {
#if SPIFFS_READ_ONLY
(void)fs; (void)path;
return SPIFFS_ERR_RO_NOT_IMPL;
#else
SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_API_CHECK_MOUNT(fs);
if (strlen(path) > SPIFFS_OBJ_NAME_LEN - 1) {
SPIFFS_API_CHECK_RES(fs, SPIFFS_ERR_NAME_TOO_LONG);
}
SPIFFS_LOCK(fs); SPIFFS_LOCK(fs);
spiffs_fd *fd; spiffs_fd *fd;
...@@ -503,7 +629,7 @@ s32_t SPIFFS_remove(spiffs *fs, char *path) { ...@@ -503,7 +629,7 @@ s32_t SPIFFS_remove(spiffs *fs, char *path) {
res = spiffs_fd_find_new(fs, &fd); res = spiffs_fd_find_new(fs, &fd);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
res = spiffs_object_find_object_index_header_by_name(fs, (u8_t *)path, &pix); res = spiffs_object_find_object_index_header_by_name(fs, (const u8_t*)path, &pix);
if (res != SPIFFS_OK) { if (res != SPIFFS_OK) {
spiffs_fd_return(fs, fd->file_nbr); spiffs_fd_return(fs, fd->file_nbr);
} }
...@@ -523,19 +649,25 @@ s32_t SPIFFS_remove(spiffs *fs, char *path) { ...@@ -523,19 +649,25 @@ s32_t SPIFFS_remove(spiffs *fs, char *path) {
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return 0; return 0;
#endif // SPIFFS_READ_ONLY
} }
s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) { s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) {
#if SPIFFS_READ_ONLY
(void)fs; (void)fh;
return SPIFFS_ERR_RO_NOT_IMPL;
#else
SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_API_CHECK_MOUNT(fs);
SPIFFS_LOCK(fs); SPIFFS_LOCK(fs);
spiffs_fd *fd; spiffs_fd *fd;
s32_t res; s32_t res;
fh = SPIFFS_FH_UNOFFS(fs, fh);
res = spiffs_fd_get(fs, fh, &fd); res = spiffs_fd_get(fs, fh, &fd);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
if ((fd->flags & SPIFFS_WRONLY) == 0) { if ((fd->flags & SPIFFS_O_WRONLY) == 0) {
res = SPIFFS_ERR_NOT_WRITABLE; res = SPIFFS_ERR_NOT_WRITABLE;
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
} }
...@@ -551,9 +683,11 @@ s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) { ...@@ -551,9 +683,11 @@ s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) {
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return 0; return 0;
#endif // SPIFFS_READ_ONLY
} }
static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file fh, spiffs_stat *s) { static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file fh, spiffs_stat *s) {
(void)fh;
spiffs_page_object_ix_header objix_hdr; spiffs_page_object_ix_header objix_hdr;
spiffs_obj_id obj_id; spiffs_obj_id obj_id;
s32_t res =_spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ, fh, s32_t res =_spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ, fh,
...@@ -566,23 +700,27 @@ static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file fh, spi ...@@ -566,23 +700,27 @@ static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file fh, spi
obj_id_addr, sizeof(spiffs_obj_id), (u8_t *)&obj_id); obj_id_addr, sizeof(spiffs_obj_id), (u8_t *)&obj_id);
SPIFFS_API_CHECK_RES(fs, res); SPIFFS_API_CHECK_RES(fs, res);
s->obj_id = obj_id; s->obj_id = obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
s->type = objix_hdr.type; s->type = objix_hdr.type;
s->size = objix_hdr.size == SPIFFS_UNDEFINED_LEN ? 0 : objix_hdr.size; s->size = objix_hdr.size == SPIFFS_UNDEFINED_LEN ? 0 : objix_hdr.size;
s->pix = pix;
strncpy((char *)s->name, (char *)objix_hdr.name, SPIFFS_OBJ_NAME_LEN); strncpy((char *)s->name, (char *)objix_hdr.name, SPIFFS_OBJ_NAME_LEN);
return res; return res;
} }
s32_t SPIFFS_stat(spiffs *fs, char *path, spiffs_stat *s) { s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s) {
SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_API_CHECK_MOUNT(fs);
if (strlen(path) > SPIFFS_OBJ_NAME_LEN - 1) {
SPIFFS_API_CHECK_RES(fs, SPIFFS_ERR_NAME_TOO_LONG);
}
SPIFFS_LOCK(fs); SPIFFS_LOCK(fs);
s32_t res; s32_t res;
spiffs_page_ix pix; spiffs_page_ix pix;
res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)path, &pix); res = spiffs_object_find_object_index_header_by_name(fs, (const u8_t*)path, &pix);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
res = spiffs_stat_pix(fs, pix, 0, s); res = spiffs_stat_pix(fs, pix, 0, s);
...@@ -600,6 +738,7 @@ s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) { ...@@ -600,6 +738,7 @@ s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) {
spiffs_fd *fd; spiffs_fd *fd;
s32_t res; s32_t res;
fh = SPIFFS_FH_UNOFFS(fs, fh);
res = spiffs_fd_get(fs, fh, &fd); res = spiffs_fd_get(fs, fh, &fd);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
...@@ -616,15 +755,18 @@ s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) { ...@@ -616,15 +755,18 @@ s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) {
// Checks if there are any cached writes for the object id associated with // Checks if there are any cached writes for the object id associated with
// given filehandle. If so, these writes are flushed. // given filehandle. If so, these writes are flushed.
#if SPIFFS_CACHE == 1
static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) { static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) {
(void)fs;
(void)fh;
s32_t res = SPIFFS_OK; s32_t res = SPIFFS_OK;
#if SPIFFS_CACHE_WR #if !SPIFFS_READ_ONLY && SPIFFS_CACHE_WR
spiffs_fd *fd; spiffs_fd *fd;
res = spiffs_fd_get(fs, fh, &fd); res = spiffs_fd_get(fs, fh, &fd);
SPIFFS_API_CHECK_RES(fs, res); SPIFFS_API_CHECK_RES(fs, res);
if ((fd->flags & SPIFFS_DIRECT) == 0) { if ((fd->flags & SPIFFS_O_DIRECT) == 0) {
if (fd->cache_page == 0) { if (fd->cache_page == 0) {
// see if object id is associated with cache already // see if object id is associated with cache already
fd->cache_page = spiffs_cache_page_get_by_fd(fs, fd); fd->cache_page = spiffs_cache_page_get_by_fd(fs, fd);
...@@ -645,13 +787,16 @@ static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) { ...@@ -645,13 +787,16 @@ static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) {
return res; return res;
} }
#endif
s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) { s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) {
(void)fh;
SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_API_CHECK_MOUNT(fs);
s32_t res = SPIFFS_OK; s32_t res = SPIFFS_OK;
#if SPIFFS_CACHE_WR #if !SPIFFS_READ_ONLY && SPIFFS_CACHE_WR
SPIFFS_LOCK(fs); SPIFFS_LOCK(fs);
fh = SPIFFS_FH_UNOFFS(fs, fh);
res = spiffs_fflush_cache(fs, fh); res = spiffs_fflush_cache(fs, fh);
SPIFFS_API_CHECK_RES_UNLOCK(fs,res); SPIFFS_API_CHECK_RES_UNLOCK(fs,res);
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
...@@ -660,38 +805,46 @@ s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) { ...@@ -660,38 +805,46 @@ s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) {
return res; return res;
} }
void SPIFFS_close(spiffs *fs, spiffs_file fh) { s32_t SPIFFS_close(spiffs *fs, spiffs_file fh) {
if (!SPIFFS_CHECK_CFG((fs))) { SPIFFS_API_CHECK_CFG(fs);
(fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; SPIFFS_API_CHECK_MOUNT(fs);
return;
}
if (!SPIFFS_CHECK_MOUNT(fs)) { s32_t res = SPIFFS_OK;
fs->err_code = SPIFFS_ERR_NOT_MOUNTED;
return;
}
SPIFFS_LOCK(fs); SPIFFS_LOCK(fs);
fh = SPIFFS_FH_UNOFFS(fs, fh);
#if SPIFFS_CACHE #if SPIFFS_CACHE
spiffs_fflush_cache(fs, fh); res = spiffs_fflush_cache(fs, fh);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
#endif #endif
spiffs_fd_return(fs, fh); res = spiffs_fd_return(fs, fh);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return res;
} }
s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) { s32_t SPIFFS_rename(spiffs *fs, const char *old_path, const char *new_path) {
#if SPIFFS_READ_ONLY
(void)fs; (void)old_path; (void)new_path;
return SPIFFS_ERR_RO_NOT_IMPL;
#else
SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_API_CHECK_MOUNT(fs);
if (strlen(new_path) > SPIFFS_OBJ_NAME_LEN - 1 ||
strlen(old_path) > SPIFFS_OBJ_NAME_LEN - 1) {
SPIFFS_API_CHECK_RES(fs, SPIFFS_ERR_NAME_TOO_LONG);
}
SPIFFS_LOCK(fs); SPIFFS_LOCK(fs);
spiffs_page_ix pix_old, pix_dummy; spiffs_page_ix pix_old, pix_dummy;
spiffs_fd *fd; spiffs_fd *fd;
s32_t res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)old, &pix_old); s32_t res = spiffs_object_find_object_index_header_by_name(fs, (const u8_t*)old_path, &pix_old);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)new, &pix_dummy); res = spiffs_object_find_object_index_header_by_name(fs, (const u8_t*)new_path, &pix_dummy);
if (res == SPIFFS_ERR_NOT_FOUND) { if (res == SPIFFS_ERR_NOT_FOUND) {
res = SPIFFS_OK; res = SPIFFS_OK;
} else if (res == SPIFFS_OK) { } else if (res == SPIFFS_OK) {
...@@ -708,7 +861,7 @@ s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) { ...@@ -708,7 +861,7 @@ s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) {
} }
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, fd->objix_hdr_pix, 0, (u8_t*)new, res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, fd->objix_hdr_pix, 0, (const u8_t*)new_path,
0, &pix_dummy); 0, &pix_dummy);
spiffs_fd_return(fs, fd->file_nbr); spiffs_fd_return(fs, fd->file_nbr);
...@@ -718,9 +871,10 @@ s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) { ...@@ -718,9 +871,10 @@ s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) {
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return res; return res;
#endif // SPIFFS_READ_ONLY
} }
spiffs_DIR *SPIFFS_opendir(spiffs *fs, char *name, spiffs_DIR *d) { spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d) {
(void)name; (void)name;
if (!SPIFFS_CHECK_CFG((fs))) { if (!SPIFFS_CHECK_CFG((fs))) {
...@@ -744,9 +898,9 @@ static s32_t spiffs_read_dir_v( ...@@ -744,9 +898,9 @@ static s32_t spiffs_read_dir_v(
spiffs_obj_id obj_id, spiffs_obj_id obj_id,
spiffs_block_ix bix, spiffs_block_ix bix,
int ix_entry, int ix_entry,
u32_t user_data, const void *user_const_p,
void *user_p) { void *user_var_p) {
(void)user_data; (void)user_const_p;
s32_t res; s32_t res;
spiffs_page_object_ix_header objix_hdr; spiffs_page_object_ix_header objix_hdr;
if (obj_id == SPIFFS_OBJ_ID_FREE || obj_id == SPIFFS_OBJ_ID_DELETED || if (obj_id == SPIFFS_OBJ_ID_FREE || obj_id == SPIFFS_OBJ_ID_DELETED ||
...@@ -762,10 +916,9 @@ static s32_t spiffs_read_dir_v( ...@@ -762,10 +916,9 @@ static s32_t spiffs_read_dir_v(
objix_hdr.p_hdr.span_ix == 0 && objix_hdr.p_hdr.span_ix == 0 &&
(objix_hdr.p_hdr.flags& (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE)) == (objix_hdr.p_hdr.flags& (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE)) ==
(SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) { (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) {
struct spiffs_dirent *e = (struct spiffs_dirent *)user_p; struct spiffs_dirent *e = (struct spiffs_dirent*)user_var_p;
e->obj_id = obj_id; e->obj_id = obj_id;
strncpy((char *)e->name, (char *)objix_hdr.name, SPIFFS_OBJ_NAME_LEN); strcpy((char *)e->name, (char *)objix_hdr.name);
e->type = objix_hdr.type; e->type = objix_hdr.type;
e->size = objix_hdr.size == SPIFFS_UNDEFINED_LEN ? 0 : objix_hdr.size; e->size = objix_hdr.size == SPIFFS_UNDEFINED_LEN ? 0 : objix_hdr.size;
e->pix = pix; e->pix = pix;
...@@ -780,7 +933,7 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) { ...@@ -780,7 +933,7 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) {
d->fs->err_code = SPIFFS_ERR_NOT_MOUNTED; d->fs->err_code = SPIFFS_ERR_NOT_MOUNTED;
return 0; return 0;
} }
SPIFFS_LOCK(fs); SPIFFS_LOCK(d->fs);
spiffs_block_ix bix; spiffs_block_ix bix;
int entry; int entry;
...@@ -804,7 +957,7 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) { ...@@ -804,7 +957,7 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) {
} else { } else {
d->fs->err_code = res; d->fs->err_code = res;
} }
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(d->fs);
return ret; return ret;
} }
...@@ -815,6 +968,10 @@ s32_t SPIFFS_closedir(spiffs_DIR *d) { ...@@ -815,6 +968,10 @@ s32_t SPIFFS_closedir(spiffs_DIR *d) {
} }
s32_t SPIFFS_check(spiffs *fs) { s32_t SPIFFS_check(spiffs *fs) {
#if SPIFFS_READ_ONLY
(void)fs;
return SPIFFS_ERR_RO_NOT_IMPL;
#else
s32_t res; s32_t res;
SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_API_CHECK_MOUNT(fs);
...@@ -830,6 +987,7 @@ s32_t SPIFFS_check(spiffs *fs) { ...@@ -830,6 +987,7 @@ s32_t SPIFFS_check(spiffs *fs) {
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return res; return res;
#endif // SPIFFS_READ_ONLY
} }
s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used) { s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used) {
...@@ -856,91 +1014,96 @@ s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used) { ...@@ -856,91 +1014,96 @@ s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used) {
return res; return res;
} }
s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) { s32_t SPIFFS_gc_quick(spiffs *fs, u16_t max_free_pages) {
#if SPIFFS_READ_ONLY
(void)fs; (void)max_free_pages;
return SPIFFS_ERR_RO_NOT_IMPL;
#else
s32_t res;
SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_API_CHECK_MOUNT(fs);
SPIFFS_LOCK(fs); SPIFFS_LOCK(fs);
spiffs_fd *fd; res = spiffs_gc_quick(fs, max_free_pages);
s32_t res;
res = spiffs_fd_get(fs, fh, &fd);
SPIFFS_API_CHECK_RES(fs, res);
#if SPIFFS_CACHE_WR
spiffs_fflush_cache(fs, fh);
#endif
res = fd->fdoffset;
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return res; return 0;
#endif // SPIFFS_READ_ONLY
} }
s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh) {
SPIFFS_API_CHECK_MOUNT(fs);
SPIFFS_LOCK(fs);
spiffs_fd *fd; s32_t SPIFFS_gc(spiffs *fs, u32_t size) {
#if SPIFFS_READ_ONLY
(void)fs; (void)size;
return SPIFFS_ERR_RO_NOT_IMPL;
#else
s32_t res; s32_t res;
res = spiffs_fd_get(fs, fh, &fd); SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_RES(fs, res); SPIFFS_API_CHECK_MOUNT(fs);
SPIFFS_LOCK(fs);
#if SPIFFS_CACHE_WR
spiffs_fflush_cache(fs, fh);
#endif
res = (fd->fdoffset == fd->size); res = spiffs_gc_check(fs, size);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return res; return 0;
#endif // SPIFFS_READ_ONLY
} }
s32_t SPIFFS_size(spiffs *fs, spiffs_file fh) { s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh) {
s32_t res;
SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_API_CHECK_MOUNT(fs);
SPIFFS_LOCK(fs); SPIFFS_LOCK(fs);
fh = SPIFFS_FH_UNOFFS(fs, fh);
spiffs_fd *fd; spiffs_fd *fd;
s32_t res;
res = spiffs_fd_get(fs, fh, &fd); res = spiffs_fd_get(fs, fh, &fd);
SPIFFS_API_CHECK_RES(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
#if SPIFFS_CACHE_WR #if SPIFFS_CACHE_WR
spiffs_fflush_cache(fs, fh); res = spiffs_fflush_cache(fs, fh);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
#endif #endif
res = fd->size; res = (fd->fdoffset >= (fd->size == SPIFFS_UNDEFINED_LEN ? 0 : fd->size));
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return res; return res;
} }
s32_t SPIFFS_gc_quick(spiffs *fs, u16_t max_free_pages) { s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) {
s32_t res; s32_t res;
SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_API_CHECK_MOUNT(fs);
SPIFFS_LOCK(fs); SPIFFS_LOCK(fs);
res = spiffs_gc_quick(fs, max_free_pages); fh = SPIFFS_FH_UNOFFS(fs, fh);
spiffs_fd *fd;
res = spiffs_fd_get(fs, fh, &fd);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
SPIFFS_UNLOCK(fs);
return 0;
}
#if SPIFFS_CACHE_WR
res = spiffs_fflush_cache(fs, fh);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
#endif
s32_t SPIFFS_gc(spiffs *fs, u32_t size) { res = fd->fdoffset;
s32_t res;
SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs);
SPIFFS_LOCK(fs);
res = spiffs_gc_check(fs, size); SPIFFS_UNLOCK(fs);
return res;
}
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); s32_t SPIFFS_set_file_callback_func(spiffs *fs, spiffs_file_callback cb_func) {
SPIFFS_LOCK(fs);
fs->file_cb_f = cb_func;
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return 0; return 0;
} }
#if SPIFFS_TEST_VISUALISATION #if SPIFFS_TEST_VISUALISATION
s32_t SPIFFS_vis(spiffs *fs) { s32_t SPIFFS_vis(spiffs *fs) {
s32_t res = SPIFFS_OK; s32_t res = SPIFFS_OK;
...@@ -1008,11 +1171,10 @@ s32_t SPIFFS_vis(spiffs *fs) { ...@@ -1008,11 +1171,10 @@ s32_t SPIFFS_vis(spiffs *fs) {
spiffs_printf("free_blocks: %i\n", fs->free_blocks); spiffs_printf("free_blocks: %i\n", fs->free_blocks);
spiffs_printf("page_alloc: %i\n", fs->stats_p_allocated); spiffs_printf("page_alloc: %i\n", fs->stats_p_allocated);
spiffs_printf("page_delet: %i\n", fs->stats_p_deleted); spiffs_printf("page_delet: %i\n", fs->stats_p_deleted);
SPIFFS_UNLOCK(fs);
u32_t total, used; u32_t total, used;
SPIFFS_info(fs, &total, &used); SPIFFS_info(fs, &total, &used);
spiffs_printf("used: %i of %i\n", used, total); spiffs_printf("used: %i of %i\n", used, total);
SPIFFS_UNLOCK(fs);
return res; return res;
} }
#endif #endif
#include "spiffs.h" #include "spiffs.h"
#include "spiffs_nucleus.h" #include "spiffs_nucleus.h"
#include <string.h>
static s32_t spiffs_page_data_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix pix, spiffs_span_ix spix) { static s32_t spiffs_page_data_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix pix, spiffs_span_ix spix) {
s32_t res = SPIFFS_OK; s32_t res = SPIFFS_OK;
...@@ -29,6 +30,7 @@ static s32_t spiffs_page_data_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix pi ...@@ -29,6 +30,7 @@ static s32_t spiffs_page_data_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix pi
return res; return res;
} }
#if !SPIFFS_READ_ONLY
static s32_t spiffs_page_index_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix pix, spiffs_span_ix spix) { static s32_t spiffs_page_index_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix pix, spiffs_span_ix spix) {
s32_t res = SPIFFS_OK; s32_t res = SPIFFS_OK;
if (pix == (spiffs_page_ix)-1) { if (pix == (spiffs_page_ix)-1) {
...@@ -56,6 +58,7 @@ static s32_t spiffs_page_index_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix p ...@@ -56,6 +58,7 @@ static s32_t spiffs_page_index_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix p
#endif #endif
return res; return res;
} }
#endif // !SPIFFS_READ_ONLY
#if !SPIFFS_CACHE #if !SPIFFS_CACHE
...@@ -64,7 +67,7 @@ s32_t spiffs_phys_rd( ...@@ -64,7 +67,7 @@ s32_t spiffs_phys_rd(
u32_t addr, u32_t addr,
u32_t len, u32_t len,
u8_t *dst) { u8_t *dst) {
return fs->cfg.hal_read_f(addr, len, dst); return SPIFFS_HAL_READ(fs, addr, len, dst);
} }
s32_t spiffs_phys_wr( s32_t spiffs_phys_wr(
...@@ -72,17 +75,19 @@ s32_t spiffs_phys_wr( ...@@ -72,17 +75,19 @@ s32_t spiffs_phys_wr(
u32_t addr, u32_t addr,
u32_t len, u32_t len,
u8_t *src) { u8_t *src) {
return fs->cfg.hal_write_f(addr, len, src); return SPIFFS_HAL_WRITE(fs, addr, len, src);
} }
#endif #endif
#if !SPIFFS_READ_ONLY
s32_t spiffs_phys_cpy( s32_t spiffs_phys_cpy(
spiffs *fs, spiffs *fs,
spiffs_file fh, spiffs_file fh,
u32_t dst, u32_t dst,
u32_t src, u32_t src,
u32_t len) { u32_t len) {
(void)fh;
s32_t res; s32_t res;
u8_t b[SPIFFS_COPY_BUFFER_STACK]; u8_t b[SPIFFS_COPY_BUFFER_STACK];
while (len > 0) { while (len > 0) {
...@@ -97,10 +102,11 @@ s32_t spiffs_phys_cpy( ...@@ -97,10 +102,11 @@ s32_t spiffs_phys_cpy(
} }
return SPIFFS_OK; return SPIFFS_OK;
} }
#endif // !SPIFFS_READ_ONLY
// Find object lookup entry containing given id with visitor. // Find object lookup entry containing given id with visitor.
// Iterate over object lookup pages in each block until a given object id entry is found. // Iterate over object lookup pages in each block until a given object id entry is found.
// When found, the visitor function is called with block index, entry index and user_data. // When found, the visitor function is called with block index, entry index and user data.
// If visitor returns SPIFFS_VIS_CONTINUE, the search goes on. Otherwise, the search will be // If visitor returns SPIFFS_VIS_CONTINUE, the search goes on. Otherwise, the search will be
// ended and visitor's return code is returned to caller. // ended and visitor's return code is returned to caller.
// If no visitor is given (0) the search returns on first entry with matching object id. // If no visitor is given (0) the search returns on first entry with matching object id.
...@@ -112,8 +118,8 @@ s32_t spiffs_phys_cpy( ...@@ -112,8 +118,8 @@ s32_t spiffs_phys_cpy(
// SPIFFS_VIS_NO_WRAP // SPIFFS_VIS_NO_WRAP
// @param obj_id argument object id // @param obj_id argument object id
// @param v visitor callback function // @param v visitor callback function
// @param user_data any data, passed to the callback visitor function // @param user_const_p any const pointer, passed to the callback visitor function
// @param user_p any pointer, passed to the callback visitor function // @param user_var_p any pointer, passed to the callback visitor function
// @param block_ix reported block index where match was found // @param block_ix reported block index where match was found
// @param lu_entry reported look up index where match was found // @param lu_entry reported look up index where match was found
s32_t spiffs_obj_lu_find_entry_visitor( s32_t spiffs_obj_lu_find_entry_visitor(
...@@ -123,8 +129,8 @@ s32_t spiffs_obj_lu_find_entry_visitor( ...@@ -123,8 +129,8 @@ s32_t spiffs_obj_lu_find_entry_visitor(
u8_t flags, u8_t flags,
spiffs_obj_id obj_id, spiffs_obj_id obj_id,
spiffs_visitor_f v, spiffs_visitor_f v,
u32_t user_data, const void *user_const_p,
void *user_p, void *user_var_p,
spiffs_block_ix *block_ix, spiffs_block_ix *block_ix,
int *lu_entry) { int *lu_entry) {
s32_t res = SPIFFS_OK; s32_t res = SPIFFS_OK;
...@@ -174,8 +180,8 @@ s32_t spiffs_obj_lu_find_entry_visitor( ...@@ -174,8 +180,8 @@ s32_t spiffs_obj_lu_find_entry_visitor(
(flags & SPIFFS_VIS_CHECK_PH) ? obj_id : obj_lu_buf[cur_entry-entry_offset], (flags & SPIFFS_VIS_CHECK_PH) ? obj_id : obj_lu_buf[cur_entry-entry_offset],
cur_block, cur_block,
cur_entry, cur_entry,
user_data, user_const_p,
user_p); user_var_p);
if (res == SPIFFS_VIS_COUNTINUE || res == SPIFFS_VIS_COUNTINUE_RELOAD) { if (res == SPIFFS_VIS_COUNTINUE || res == SPIFFS_VIS_COUNTINUE_RELOAD) {
if (res == SPIFFS_VIS_COUNTINUE_RELOAD) { if (res == SPIFFS_VIS_COUNTINUE_RELOAD) {
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ, res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
...@@ -217,6 +223,7 @@ s32_t spiffs_obj_lu_find_entry_visitor( ...@@ -217,6 +223,7 @@ s32_t spiffs_obj_lu_find_entry_visitor(
return SPIFFS_VIS_END; return SPIFFS_VIS_END;
} }
#if !SPIFFS_READ_ONLY
s32_t spiffs_erase_block( s32_t spiffs_erase_block(
spiffs *fs, spiffs *fs,
spiffs_block_ix bix) { spiffs_block_ix bix) {
...@@ -227,7 +234,8 @@ s32_t spiffs_erase_block( ...@@ -227,7 +234,8 @@ s32_t spiffs_erase_block(
// here we ignore res, just try erasing the block // here we ignore res, just try erasing the block
while (size > 0) { while (size > 0) {
SPIFFS_DBG("erase %08x:%08x\n", addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs)); SPIFFS_DBG("erase %08x:%08x\n", addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
(void)fs->cfg.hal_erase_f(addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs)); SPIFFS_HAL_ERASE(fs, addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
addr += SPIFFS_CFG_PHYS_ERASE_SZ(fs); addr += SPIFFS_CFG_PHYS_ERASE_SZ(fs);
size -= SPIFFS_CFG_PHYS_ERASE_SZ(fs); size -= SPIFFS_CFG_PHYS_ERASE_SZ(fs);
} }
...@@ -241,7 +249,7 @@ s32_t spiffs_erase_block( ...@@ -241,7 +249,7 @@ s32_t spiffs_erase_block(
#if SPIFFS_USE_MAGIC #if SPIFFS_USE_MAGIC
// finally, write magic // finally, write magic
spiffs_obj_id magic = SPIFFS_MAGIC(fs); spiffs_obj_id magic = SPIFFS_MAGIC(fs, bix);
res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0, res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0,
SPIFFS_MAGIC_PADDR(fs, bix), SPIFFS_MAGIC_PADDR(fs, bix),
sizeof(spiffs_obj_id), (u8_t *)&magic); sizeof(spiffs_obj_id), (u8_t *)&magic);
...@@ -255,6 +263,59 @@ s32_t spiffs_erase_block( ...@@ -255,6 +263,59 @@ s32_t spiffs_erase_block(
return res; return res;
} }
#endif // !SPIFFS_READ_ONLY
#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
s32_t spiffs_probe(
spiffs_config *cfg) {
s32_t res;
u32_t paddr;
spiffs dummy_fs; // create a dummy fs struct just to be able to use macros
memcpy(&dummy_fs.cfg, cfg, sizeof(spiffs_config));
dummy_fs.block_count = 0;
// Read three magics, as one block may be in an aborted erase state.
// At least two of these must contain magic and be in decreasing order.
spiffs_obj_id magic[3];
spiffs_obj_id bix_count[3];
spiffs_block_ix bix;
for (bix = 0; bix < 3; bix++) {
paddr = SPIFFS_MAGIC_PADDR(&dummy_fs, bix);
#if SPIFFS_HAL_CALLBACK_EXTRA
// not any proper fs to report here, so callback with null
// (cross fingers that no-one gets angry)
res = cfg->hal_read_f((void *)0, paddr, sizeof(spiffs_obj_id), (u8_t *)&magic[bix]);
#else
res = cfg->hal_read_f(paddr, sizeof(spiffs_obj_id), (u8_t *)&magic[bix]);
#endif
bix_count[bix] = magic[bix] ^ SPIFFS_MAGIC(&dummy_fs, 0);
SPIFFS_CHECK_RES(res);
}
// check that we have sane number of blocks
if (bix_count[0] < 3) return SPIFFS_ERR_PROBE_TOO_FEW_BLOCKS;
// check that the order is correct, take aborted erases in calculation
// first block aborted erase
if (magic[0] == (spiffs_obj_id)(-1) && bix_count[1] - bix_count[2] == 1) {
return (bix_count[1]+1) * cfg->log_block_size;
}
// second block aborted erase
if (magic[1] == (spiffs_obj_id)(-1) && bix_count[0] - bix_count[2] == 2) {
return bix_count[0] * cfg->log_block_size;
}
// third block aborted erase
if (magic[2] == (spiffs_obj_id)(-1) && bix_count[0] - bix_count[1] == 1) {
return bix_count[0] * cfg->log_block_size;
}
// no block has aborted erase
if (bix_count[0] - bix_count[1] == 1 && bix_count[1] - bix_count[2] == 1) {
return bix_count[0] * cfg->log_block_size;
}
return SPIFFS_ERR_PROBE_NOT_A_FS;
}
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
static s32_t spiffs_obj_lu_scan_v( static s32_t spiffs_obj_lu_scan_v(
...@@ -262,11 +323,11 @@ static s32_t spiffs_obj_lu_scan_v( ...@@ -262,11 +323,11 @@ static s32_t spiffs_obj_lu_scan_v(
spiffs_obj_id obj_id, spiffs_obj_id obj_id,
spiffs_block_ix bix, spiffs_block_ix bix,
int ix_entry, int ix_entry,
u32_t user_data, const void *user_const_p,
void *user_p) { void *user_var_p) {
(void)bix; (void)bix;
(void)user_data; (void)user_const_p;
(void)user_p; (void)user_var_p;
if (obj_id == SPIFFS_OBJ_ID_FREE) { if (obj_id == SPIFFS_OBJ_ID_FREE) {
if (ix_entry == 0) { if (ix_entry == 0) {
fs->free_blocks++; fs->free_blocks++;
...@@ -309,7 +370,7 @@ s32_t spiffs_obj_lu_scan( ...@@ -309,7 +370,7 @@ s32_t spiffs_obj_lu_scan(
sizeof(spiffs_obj_id), (u8_t *)&magic); sizeof(spiffs_obj_id), (u8_t *)&magic);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
if (magic != SPIFFS_MAGIC(fs)) { if (magic != SPIFFS_MAGIC(fs, bix)) {
if (unerased_bix == (spiffs_block_ix)-1) { if (unerased_bix == (spiffs_block_ix)-1) {
// allow one unerased block as it might be powered down during an erase // allow one unerased block as it might be powered down during an erase
unerased_bix = bix; unerased_bix = bix;
...@@ -348,7 +409,11 @@ s32_t spiffs_obj_lu_scan( ...@@ -348,7 +409,11 @@ s32_t spiffs_obj_lu_scan(
if (unerased_bix != (spiffs_block_ix)-1) { if (unerased_bix != (spiffs_block_ix)-1) {
// found one unerased block, remedy // found one unerased block, remedy
SPIFFS_DBG("mount: erase block %i\n", bix); SPIFFS_DBG("mount: erase block %i\n", bix);
#if SPIFFS_READ_ONLY
res = SPIFFS_ERR_RO_ABORTED_OPERATION;
#else
res = spiffs_erase_block(fs, unerased_bix); res = spiffs_erase_block(fs, unerased_bix);
#endif // SPIFFS_READ_ONLY
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
} }
#endif #endif
...@@ -379,6 +444,7 @@ s32_t spiffs_obj_lu_scan( ...@@ -379,6 +444,7 @@ s32_t spiffs_obj_lu_scan(
return res; return res;
} }
#if !SPIFFS_READ_ONLY
// Find free object lookup entry // Find free object lookup entry
// Iterate over object lookup pages in each block until a free object id entry is found // Iterate over object lookup pages in each block until a free object id entry is found
s32_t spiffs_obj_lu_find_free( s32_t spiffs_obj_lu_find_free(
...@@ -407,12 +473,13 @@ s32_t spiffs_obj_lu_find_free( ...@@ -407,12 +473,13 @@ s32_t spiffs_obj_lu_find_free(
fs->free_blocks--; fs->free_blocks--;
} }
} }
if (res == SPIFFS_VIS_END) { if (res == SPIFFS_ERR_FULL) {
SPIFFS_DBG("fs full\n"); SPIFFS_DBG("fs full\n");
} }
return res == SPIFFS_VIS_END ? SPIFFS_ERR_FULL : res; return res;
} }
#endif // !SPIFFS_READ_ONLY
// Find object lookup entry containing given id // Find object lookup entry containing given id
// Iterate over object lookup pages in each block until a given object id entry is found // Iterate over object lookup pages in each block until a given object id entry is found
...@@ -437,8 +504,8 @@ static s32_t spiffs_obj_lu_find_id_and_span_v( ...@@ -437,8 +504,8 @@ static s32_t spiffs_obj_lu_find_id_and_span_v(
spiffs_obj_id obj_id, spiffs_obj_id obj_id,
spiffs_block_ix bix, spiffs_block_ix bix,
int ix_entry, int ix_entry,
u32_t user_data, const void *user_const_p,
void *user_p) { void *user_var_p) {
s32_t res; s32_t res;
spiffs_page_header ph; spiffs_page_header ph;
spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry); spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry);
...@@ -446,10 +513,10 @@ static s32_t spiffs_obj_lu_find_id_and_span_v( ...@@ -446,10 +513,10 @@ static s32_t spiffs_obj_lu_find_id_and_span_v(
SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_header), (u8_t *)&ph); SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_header), (u8_t *)&ph);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
if (ph.obj_id == obj_id && if (ph.obj_id == obj_id &&
ph.span_ix == (spiffs_span_ix)user_data && ph.span_ix == *((spiffs_span_ix*)user_var_p) &&
(ph.flags & (SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_USED)) == SPIFFS_PH_FLAG_DELET && (ph.flags & (SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_USED)) == SPIFFS_PH_FLAG_DELET &&
!((obj_id & SPIFFS_OBJ_ID_IX_FLAG) && (ph.flags & SPIFFS_PH_FLAG_IXDELE) == 0 && ph.span_ix == 0) && !((obj_id & SPIFFS_OBJ_ID_IX_FLAG) && (ph.flags & SPIFFS_PH_FLAG_IXDELE) == 0 && ph.span_ix == 0) &&
(user_p == 0 || *((spiffs_page_ix *)user_p) != pix)) { (user_const_p == 0 || *((const spiffs_page_ix*)user_const_p) != pix)) {
return SPIFFS_OK; return SPIFFS_OK;
} else { } else {
return SPIFFS_VIS_COUNTINUE; return SPIFFS_VIS_COUNTINUE;
...@@ -474,8 +541,8 @@ s32_t spiffs_obj_lu_find_id_and_span( ...@@ -474,8 +541,8 @@ s32_t spiffs_obj_lu_find_id_and_span(
SPIFFS_VIS_CHECK_ID, SPIFFS_VIS_CHECK_ID,
obj_id, obj_id,
spiffs_obj_lu_find_id_and_span_v, spiffs_obj_lu_find_id_and_span_v,
(u32_t)spix,
exclusion_pix ? &exclusion_pix : 0, exclusion_pix ? &exclusion_pix : 0,
&spix,
&bix, &bix,
&entry); &entry);
...@@ -513,8 +580,8 @@ s32_t spiffs_obj_lu_find_id_and_span_by_phdr( ...@@ -513,8 +580,8 @@ s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
SPIFFS_VIS_CHECK_PH, SPIFFS_VIS_CHECK_PH,
obj_id, obj_id,
spiffs_obj_lu_find_id_and_span_v, spiffs_obj_lu_find_id_and_span_v,
(u32_t)spix,
exclusion_pix ? &exclusion_pix : 0, exclusion_pix ? &exclusion_pix : 0,
&spix,
&bix, &bix,
&entry); &entry);
...@@ -534,6 +601,7 @@ s32_t spiffs_obj_lu_find_id_and_span_by_phdr( ...@@ -534,6 +601,7 @@ s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
return res; return res;
} }
#if !SPIFFS_READ_ONLY
// Allocates a free defined page with given obj_id // Allocates a free defined page with given obj_id
// Occupies object lookup entry and page // Occupies object lookup entry and page
// data may be NULL; where only page header is stored, len and page_offs is ignored // data may be NULL; where only page header is stored, len and page_offs is ignored
...@@ -591,7 +659,9 @@ s32_t spiffs_page_allocate_data( ...@@ -591,7 +659,9 @@ s32_t spiffs_page_allocate_data(
return res; return res;
} }
#endif // !SPIFFS_READ_ONLY
#if !SPIFFS_READ_ONLY
// Moves a page from src to a free page and finalizes it. Updates page index. Page data is given in param page. // Moves a page from src to a free page and finalizes it. Updates page index. Page data is given in param page.
// If page data is null, provided header is used for metainfo and page data is physically copied. // If page data is null, provided header is used for metainfo and page data is physically copied.
s32_t spiffs_page_move( s32_t spiffs_page_move(
...@@ -654,7 +724,9 @@ s32_t spiffs_page_move( ...@@ -654,7 +724,9 @@ s32_t spiffs_page_move(
res = spiffs_page_delete(fs, src_pix); res = spiffs_page_delete(fs, src_pix);
return res; return res;
} }
#endif // !SPIFFS_READ_ONLY
#if !SPIFFS_READ_ONLY
// Deletes a page and removes it from object lookup. // Deletes a page and removes it from object lookup.
s32_t spiffs_page_delete( s32_t spiffs_page_delete(
spiffs *fs, spiffs *fs,
...@@ -683,12 +755,14 @@ s32_t spiffs_page_delete( ...@@ -683,12 +755,14 @@ s32_t spiffs_page_delete(
return res; return res;
} }
#endif // !SPIFFS_READ_ONLY
#if !SPIFFS_READ_ONLY
// Create an object index header page with empty index and undefined length // Create an object index header page with empty index and undefined length
s32_t spiffs_object_create( s32_t spiffs_object_create(
spiffs *fs, spiffs *fs,
spiffs_obj_id obj_id, spiffs_obj_id obj_id,
u8_t name[SPIFFS_OBJ_NAME_LEN], const u8_t name[SPIFFS_OBJ_NAME_LEN],
spiffs_obj_type type, spiffs_obj_type type,
spiffs_page_ix *objix_hdr_pix) { spiffs_page_ix *objix_hdr_pix) {
s32_t res = SPIFFS_OK; s32_t res = SPIFFS_OK;
...@@ -719,7 +793,7 @@ s32_t spiffs_object_create( ...@@ -719,7 +793,7 @@ s32_t spiffs_object_create(
oix_hdr.p_hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_USED); oix_hdr.p_hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_USED);
oix_hdr.type = type; oix_hdr.type = type;
oix_hdr.size = SPIFFS_UNDEFINED_LEN; // keep ones so we can update later without wasting this page oix_hdr.size = SPIFFS_UNDEFINED_LEN; // keep ones so we can update later without wasting this page
strncpy((char *)&oix_hdr.name, (char *)name, SPIFFS_OBJ_NAME_LEN); strncpy((char*)&oix_hdr.name, (const char*)name, SPIFFS_OBJ_NAME_LEN);
// update page // update page
...@@ -735,7 +809,9 @@ s32_t spiffs_object_create( ...@@ -735,7 +809,9 @@ s32_t spiffs_object_create(
return res; return res;
} }
#endif // !SPIFFS_READ_ONLY
#if !SPIFFS_READ_ONLY
// update object index header with any combination of name/size/index // update object index header with any combination of name/size/index
// new_objix_hdr_data may be null, if so the object index header page is loaded // new_objix_hdr_data may be null, if so the object index header page is loaded
// name may be null, if so name is not changed // name may be null, if so name is not changed
...@@ -746,7 +822,7 @@ s32_t spiffs_object_update_index_hdr( ...@@ -746,7 +822,7 @@ s32_t spiffs_object_update_index_hdr(
spiffs_obj_id obj_id, spiffs_obj_id obj_id,
spiffs_page_ix objix_hdr_pix, spiffs_page_ix objix_hdr_pix,
u8_t *new_objix_hdr_data, u8_t *new_objix_hdr_data,
u8_t name[SPIFFS_OBJ_NAME_LEN], const u8_t name[SPIFFS_OBJ_NAME_LEN],
u32_t size, u32_t size,
spiffs_page_ix *new_pix) { spiffs_page_ix *new_pix) {
s32_t res = SPIFFS_OK; s32_t res = SPIFFS_OK;
...@@ -770,7 +846,7 @@ s32_t spiffs_object_update_index_hdr( ...@@ -770,7 +846,7 @@ s32_t spiffs_object_update_index_hdr(
// change name // change name
if (name) { if (name) {
strncpy((char *)objix_hdr->name, (char *)name, SPIFFS_OBJ_NAME_LEN); strncpy((char*)objix_hdr->name, (const char*)name, SPIFFS_OBJ_NAME_LEN);
} }
if (size) { if (size) {
objix_hdr->size = size; objix_hdr->size = size;
...@@ -790,18 +866,19 @@ s32_t spiffs_object_update_index_hdr( ...@@ -790,18 +866,19 @@ s32_t spiffs_object_update_index_hdr(
return res; return res;
} }
#endif // !SPIFFS_READ_ONLY
void spiffs_cb_object_event( void spiffs_cb_object_event(
spiffs *fs, spiffs *fs,
spiffs_fd *fd, spiffs_fd *fd,
int ev, int ev,
spiffs_obj_id obj_id, spiffs_obj_id obj_id_raw,
spiffs_span_ix spix, spiffs_span_ix spix,
spiffs_page_ix new_pix, spiffs_page_ix new_pix,
u32_t new_size) { u32_t new_size) {
(void)fd; (void)fd;
// update index caches in all file descriptors // update index caches in all file descriptors
obj_id &= ~SPIFFS_OBJ_ID_IX_FLAG; spiffs_obj_id obj_id = obj_id_raw & ~SPIFFS_OBJ_ID_IX_FLAG;
u32_t i; u32_t i;
spiffs_fd *fds = (spiffs_fd *)fs->fd_space; spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
for (i = 0; i < fs->fd_count; i++) { for (i = 0; i < fs->fd_count; i++) {
...@@ -828,6 +905,22 @@ void spiffs_cb_object_event( ...@@ -828,6 +905,22 @@ void spiffs_cb_object_event(
} }
} }
} }
// callback to user if object index header
if (fs->file_cb_f && spix == 0 && (obj_id_raw & SPIFFS_OBJ_ID_IX_FLAG)) {
spiffs_fileop_type op;
if (ev == SPIFFS_EV_IX_NEW) {
op = SPIFFS_CB_CREATED;
} else if (ev == SPIFFS_EV_IX_UPD) {
op = SPIFFS_CB_UPDATED;
} else if (ev == SPIFFS_EV_IX_DEL) {
op = SPIFFS_CB_DELETED;
} else {
SPIFFS_DBG(" callback: WARNING unknown callback event %02x\n", ev);
return; // bail out
}
fs->file_cb_f(fs, op, obj_id, new_pix);
}
} }
// Open object by id // Open object by id
...@@ -886,6 +979,7 @@ s32_t spiffs_object_open_by_page( ...@@ -886,6 +979,7 @@ s32_t spiffs_object_open_by_page(
return res; return res;
} }
#if !SPIFFS_READ_ONLY
// Append to object // Append to object
// keep current object index (header) page in fs->work buffer // keep current object index (header) page in fs->work buffer
s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) { s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
...@@ -1125,8 +1219,10 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) { ...@@ -1125,8 +1219,10 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
} }
return res; return res;
} } // spiffs_object_append
#endif // !SPIFFS_READ_ONLY
#if !SPIFFS_READ_ONLY
// Modify object // Modify object
// keep current object index (header) page in fs->work buffer // keep current object index (header) page in fs->work buffer
s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) { s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
...@@ -1326,16 +1422,17 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) { ...@@ -1326,16 +1422,17 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
} }
return res; return res;
} } // spiffs_object_modify
#endif // !SPIFFS_READ_ONLY
static s32_t spiffs_object_find_object_index_header_by_name_v( static s32_t spiffs_object_find_object_index_header_by_name_v(
spiffs *fs, spiffs *fs,
spiffs_obj_id obj_id, spiffs_obj_id obj_id,
spiffs_block_ix bix, spiffs_block_ix bix,
int ix_entry, int ix_entry,
u32_t user_data, const void *user_const_p,
void *user_p) { void *user_var_p) {
(void)user_data; (void)user_var_p;
s32_t res; s32_t res;
spiffs_page_object_ix_header objix_hdr; spiffs_page_object_ix_header objix_hdr;
spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry); spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry);
...@@ -1349,7 +1446,7 @@ static s32_t spiffs_object_find_object_index_header_by_name_v( ...@@ -1349,7 +1446,7 @@ static s32_t spiffs_object_find_object_index_header_by_name_v(
if (objix_hdr.p_hdr.span_ix == 0 && if (objix_hdr.p_hdr.span_ix == 0 &&
(objix_hdr.p_hdr.flags & (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE)) == (objix_hdr.p_hdr.flags & (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE)) ==
(SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) { (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) {
if (strncmp((char *)user_p, (char *)objix_hdr.name, SPIFFS_OBJ_NAME_LEN) == 0) { if (strcmp((const char*)user_const_p, (char*)objix_hdr.name) == 0) {
return SPIFFS_OK; return SPIFFS_OK;
} }
} }
...@@ -1360,7 +1457,7 @@ static s32_t spiffs_object_find_object_index_header_by_name_v( ...@@ -1360,7 +1457,7 @@ static s32_t spiffs_object_find_object_index_header_by_name_v(
// Finds object index header page by name // Finds object index header page by name
s32_t spiffs_object_find_object_index_header_by_name( s32_t spiffs_object_find_object_index_header_by_name(
spiffs *fs, spiffs *fs,
u8_t name[SPIFFS_OBJ_NAME_LEN], const u8_t name[SPIFFS_OBJ_NAME_LEN],
spiffs_page_ix *pix) { spiffs_page_ix *pix) {
s32_t res; s32_t res;
spiffs_block_ix bix; spiffs_block_ix bix;
...@@ -1372,8 +1469,8 @@ s32_t spiffs_object_find_object_index_header_by_name( ...@@ -1372,8 +1469,8 @@ s32_t spiffs_object_find_object_index_header_by_name(
0, 0,
0, 0,
spiffs_object_find_object_index_header_by_name_v, spiffs_object_find_object_index_header_by_name_v,
0,
name, name,
0,
&bix, &bix,
&entry); &entry);
...@@ -1392,6 +1489,7 @@ s32_t spiffs_object_find_object_index_header_by_name( ...@@ -1392,6 +1489,7 @@ s32_t spiffs_object_find_object_index_header_by_name(
return res; return res;
} }
#if !SPIFFS_READ_ONLY
// Truncates object to new size. If new size is null, object may be removed totally // Truncates object to new size. If new size is null, object may be removed totally
s32_t spiffs_object_truncate( s32_t spiffs_object_truncate(
spiffs_fd *fd, spiffs_fd *fd,
...@@ -1400,8 +1498,16 @@ s32_t spiffs_object_truncate( ...@@ -1400,8 +1498,16 @@ s32_t spiffs_object_truncate(
s32_t res = SPIFFS_OK; s32_t res = SPIFFS_OK;
spiffs *fs = fd->fs; spiffs *fs = fd->fs;
res = spiffs_gc_check(fs, remove ? 0 : SPIFFS_DATA_PAGE_SIZE(fs)); if ((fd->size == SPIFFS_UNDEFINED_LEN || fd->size == 0) && !remove) {
// no op
return res;
}
// need 2 pages if not removing: object index page + possibly chopped data page
if (remove == 0) {
res = spiffs_gc_check(fs, SPIFFS_DATA_PAGE_SIZE(fs) * 2);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
}
spiffs_page_ix objix_pix = fd->objix_hdr_pix; spiffs_page_ix objix_pix = fd->objix_hdr_pix;
spiffs_span_ix data_spix = (fd->size > 0 ? fd->size-1 : 0) / SPIFFS_DATA_PAGE_SIZE(fs); spiffs_span_ix data_spix = (fd->size > 0 ? fd->size-1 : 0) / SPIFFS_DATA_PAGE_SIZE(fs);
...@@ -1440,11 +1546,18 @@ s32_t spiffs_object_truncate( ...@@ -1440,11 +1546,18 @@ s32_t spiffs_object_truncate(
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_DEL, fd->obj_id, objix->p_hdr.span_ix, objix_pix, 0); spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_DEL, fd->obj_id, objix->p_hdr.span_ix, objix_pix, 0);
if (prev_objix_spix > 0) { if (prev_objix_spix > 0) {
// update object index header page // Update object index header page, unless we totally want to remove the file.
// If fully removing, we're not keeping consistency as good as when storing the header between chunks,
// would we be aborted. But when removing full files, a crammed system may otherwise
// report ERR_FULL a la windows. We cannot have that.
// Hence, take the risk - if aborted, a file check would free the lost pages and mend things
// as the file is marked as fully deleted in the beginning.
if (remove == 0) {
SPIFFS_DBG("truncate: update objix hdr page %04x:%04x to size %i\n", fd->objix_hdr_pix, prev_objix_spix, cur_size); SPIFFS_DBG("truncate: update objix hdr page %04x:%04x to size %i\n", fd->objix_hdr_pix, prev_objix_spix, cur_size);
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
fd->objix_hdr_pix, 0, 0, cur_size, &new_objix_hdr_pix); fd->objix_hdr_pix, 0, 0, cur_size, &new_objix_hdr_pix);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
}
fd->size = cur_size; fd->size = cur_size;
} }
} }
...@@ -1480,7 +1593,7 @@ s32_t spiffs_object_truncate( ...@@ -1480,7 +1593,7 @@ s32_t spiffs_object_truncate(
SPIFFS_DBG("truncate: got data pix %04x\n", data_pix); SPIFFS_DBG("truncate: got data pix %04x\n", data_pix);
if (cur_size - SPIFFS_DATA_PAGE_SIZE(fs) >= new_size) { if (new_size == 0 || remove || cur_size - new_size >= SPIFFS_DATA_PAGE_SIZE(fs)) {
// delete full data page // delete full data page
res = spiffs_page_data_check(fs, fd, data_pix, data_spix); res = spiffs_page_data_check(fs, fd, data_pix, data_spix);
if (res != SPIFFS_ERR_DELETED && res != SPIFFS_OK && res != SPIFFS_ERR_INDEX_REF_FREE) { if (res != SPIFFS_ERR_DELETED && res != SPIFFS_OK && res != SPIFFS_ERR_INDEX_REF_FREE) {
...@@ -1611,7 +1724,8 @@ s32_t spiffs_object_truncate( ...@@ -1611,7 +1724,8 @@ s32_t spiffs_object_truncate(
fd->size = cur_size; fd->size = cur_size;
return res; return res;
} } // spiffs_object_truncate
#endif // !SPIFFS_READ_ONLY
s32_t spiffs_object_read( s32_t spiffs_object_read(
spiffs_fd *fd, spiffs_fd *fd,
...@@ -1691,6 +1805,7 @@ s32_t spiffs_object_read( ...@@ -1691,6 +1805,7 @@ s32_t spiffs_object_read(
return res; return res;
} }
#if !SPIFFS_READ_ONLY
typedef struct { typedef struct {
spiffs_obj_id min_obj_id; spiffs_obj_id min_obj_id;
spiffs_obj_id max_obj_id; spiffs_obj_id max_obj_id;
...@@ -1699,10 +1814,10 @@ typedef struct { ...@@ -1699,10 +1814,10 @@ typedef struct {
} spiffs_free_obj_id_state; } spiffs_free_obj_id_state;
static s32_t spiffs_obj_lu_find_free_obj_id_bitmap_v(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry, static s32_t spiffs_obj_lu_find_free_obj_id_bitmap_v(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry,
u32_t user_data, void *user_p) { const void *user_const_p, void *user_var_p) {
if (id != SPIFFS_OBJ_ID_FREE && id != SPIFFS_OBJ_ID_DELETED) { if (id != SPIFFS_OBJ_ID_FREE && id != SPIFFS_OBJ_ID_DELETED) {
spiffs_obj_id min_obj_id = user_data; spiffs_obj_id min_obj_id = *((spiffs_obj_id*)user_var_p);
u8_t *conflicting_name = (u8_t *)user_p; const u8_t *conflicting_name = (const u8_t*)user_const_p;
// if conflicting name parameter is given, also check if this name is found in object index hdrs // if conflicting name parameter is given, also check if this name is found in object index hdrs
if (conflicting_name && (id & SPIFFS_OBJ_ID_IX_FLAG)) { if (conflicting_name && (id & SPIFFS_OBJ_ID_IX_FLAG)) {
...@@ -1715,7 +1830,7 @@ static s32_t spiffs_obj_lu_find_free_obj_id_bitmap_v(spiffs *fs, spiffs_obj_id i ...@@ -1715,7 +1830,7 @@ static s32_t spiffs_obj_lu_find_free_obj_id_bitmap_v(spiffs *fs, spiffs_obj_id i
if (objix_hdr.p_hdr.span_ix == 0 && if (objix_hdr.p_hdr.span_ix == 0 &&
(objix_hdr.p_hdr.flags & (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE)) == (objix_hdr.p_hdr.flags & (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE)) ==
(SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) { (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) {
if (strncmp((char *)user_p, (char *)objix_hdr.name, SPIFFS_OBJ_NAME_LEN) == 0) { if (strcmp((const char*)user_const_p, (char*)objix_hdr.name) == 0) {
return SPIFFS_ERR_CONFLICTING_NAME; return SPIFFS_ERR_CONFLICTING_NAME;
} }
} }
...@@ -1732,11 +1847,11 @@ static s32_t spiffs_obj_lu_find_free_obj_id_bitmap_v(spiffs *fs, spiffs_obj_id i ...@@ -1732,11 +1847,11 @@ static s32_t spiffs_obj_lu_find_free_obj_id_bitmap_v(spiffs *fs, spiffs_obj_id i
} }
static s32_t spiffs_obj_lu_find_free_obj_id_compact_v(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry, static s32_t spiffs_obj_lu_find_free_obj_id_compact_v(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry,
u32_t user_data, void *user_p) { const void *user_const_p, void *user_var_p) {
(void)user_data; (void)user_var_p;
if (id != SPIFFS_OBJ_ID_FREE && id != SPIFFS_OBJ_ID_DELETED && (id & SPIFFS_OBJ_ID_IX_FLAG)) { if (id != SPIFFS_OBJ_ID_FREE && id != SPIFFS_OBJ_ID_DELETED && (id & SPIFFS_OBJ_ID_IX_FLAG)) {
s32_t res; s32_t res;
spiffs_free_obj_id_state *state = (spiffs_free_obj_id_state *)user_p; const spiffs_free_obj_id_state *state = (const spiffs_free_obj_id_state*)user_const_p;
spiffs_page_object_ix_header objix_hdr; spiffs_page_object_ix_header objix_hdr;
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
...@@ -1745,7 +1860,7 @@ static s32_t spiffs_obj_lu_find_free_obj_id_compact_v(spiffs *fs, spiffs_obj_id ...@@ -1745,7 +1860,7 @@ static s32_t spiffs_obj_lu_find_free_obj_id_compact_v(spiffs *fs, spiffs_obj_id
((objix_hdr.p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET)) == ((objix_hdr.p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET)) ==
(SPIFFS_PH_FLAG_DELET))) { (SPIFFS_PH_FLAG_DELET))) {
// ok object look up entry // ok object look up entry
if (state->conflicting_name && strncmp((const char *)state->conflicting_name, (char *)objix_hdr.name, SPIFFS_OBJ_NAME_LEN) == 0) { if (state->conflicting_name && strcmp((const char *)state->conflicting_name, (char *)objix_hdr.name) == 0) {
return SPIFFS_ERR_CONFLICTING_NAME; return SPIFFS_ERR_CONFLICTING_NAME;
} }
...@@ -1764,10 +1879,10 @@ static s32_t spiffs_obj_lu_find_free_obj_id_compact_v(spiffs *fs, spiffs_obj_id ...@@ -1764,10 +1879,10 @@ static s32_t spiffs_obj_lu_find_free_obj_id_compact_v(spiffs *fs, spiffs_obj_id
// Scans thru all object lookup for object index header pages. If total possible number of // Scans thru all object lookup for object index header pages. If total possible number of
// object ids cannot fit into a work buffer, these are grouped. When a group containing free // object ids cannot fit into a work buffer, these are grouped. When a group containing free
// object ids is found, the object lu is again scanned for object ids within group and bitmasked. // object ids is found, the object lu is again scanned for object ids within group and bitmasked.
// Finally, the bitmasked is searched for a free id // Finally, the bitmask is searched for a free id
s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, u8_t *conflicting_name) { s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, const u8_t *conflicting_name) {
s32_t res = SPIFFS_OK; s32_t res = SPIFFS_OK;
u32_t max_objects = (SPIFFS_CFG_PHYS_SZ(fs) / (u32_t)SPIFFS_CFG_LOG_PAGE_SZ(fs)) / 2; u32_t max_objects = (fs->block_count * SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs)) / 2;
spiffs_free_obj_id_state state; spiffs_free_obj_id_state state;
spiffs_obj_id free_obj_id = SPIFFS_OBJ_ID_FREE; spiffs_obj_id free_obj_id = SPIFFS_OBJ_ID_FREE;
state.min_obj_id = 1; state.min_obj_id = 1;
...@@ -1784,8 +1899,8 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, u8_t *co ...@@ -1784,8 +1899,8 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, u8_t *co
SPIFFS_DBG("free_obj_id: BITM min:%04x max:%04x\n", state.min_obj_id, state.max_obj_id); SPIFFS_DBG("free_obj_id: BITM min:%04x max:%04x\n", state.min_obj_id, state.max_obj_id);
memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs)); memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_obj_lu_find_free_obj_id_bitmap_v, state.min_obj_id, res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_obj_lu_find_free_obj_id_bitmap_v,
conflicting_name, 0, 0); conflicting_name, &state.min_obj_id, 0, 0);
if (res == SPIFFS_VIS_END) res = SPIFFS_OK; if (res == SPIFFS_VIS_END) res = SPIFFS_OK;
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
// traverse bitmask until found free obj_id // traverse bitmask until found free obj_id
...@@ -1849,7 +1964,7 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, u8_t *co ...@@ -1849,7 +1964,7 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, u8_t *co
SPIFFS_DBG("free_obj_id: COMP min:%04x max:%04x compact:%i\n", state.min_obj_id, state.max_obj_id, state.compaction); SPIFFS_DBG("free_obj_id: COMP min:%04x max:%04x compact:%i\n", state.min_obj_id, state.max_obj_id, state.compaction);
memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs)); memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_obj_lu_find_free_obj_id_compact_v, 0, &state, 0, 0); res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_obj_lu_find_free_obj_id_compact_v, &state, 0, 0, 0);
if (res == SPIFFS_VIS_END) res = SPIFFS_OK; if (res == SPIFFS_VIS_END) res = SPIFFS_OK;
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
state.conflicting_name = 0; // searched for conflicting name once, no need to do it again state.conflicting_name = 0; // searched for conflicting name once, no need to do it again
...@@ -1858,6 +1973,7 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, u8_t *co ...@@ -1858,6 +1973,7 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, u8_t *co
return res; return res;
} }
#endif // !SPIFFS_READ_ONLY
s32_t spiffs_fd_find_new(spiffs *fs, spiffs_fd **fd) { s32_t spiffs_fd_find_new(spiffs *fs, spiffs_fd **fd) {
u32_t i; u32_t i;
......
...@@ -131,7 +131,15 @@ ...@@ -131,7 +131,15 @@
#define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0) #define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0)
#define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1) #define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1)
#define SPIFFS_MAGIC(fs) ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs))) #if SPIFFS_USE_MAGIC
#if !SPIFFS_USE_MAGIC_LENGTH
#define SPIFFS_MAGIC(fs, bix) \
((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs)))
#else // SPIFFS_USE_MAGIC_LENGTH
#define SPIFFS_MAGIC(fs, bix) \
((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs) ^ ((fs)->block_count - (bix))))
#endif // SPIFFS_USE_MAGIC_LENGTH
#endif // SPIFFS_USE_MAGIC
#define SPIFFS_CONFIG_MAGIC (0x20090315) #define SPIFFS_CONFIG_MAGIC (0x20090315)
...@@ -264,26 +272,26 @@ ...@@ -264,26 +272,26 @@
#define SPIFFS_API_CHECK_MOUNT(fs) \ #define SPIFFS_API_CHECK_MOUNT(fs) \
if (!SPIFFS_CHECK_MOUNT((fs))) { \ if (!SPIFFS_CHECK_MOUNT((fs))) { \
(fs)->err_code = SPIFFS_ERR_NOT_MOUNTED; \ (fs)->err_code = SPIFFS_ERR_NOT_MOUNTED; \
return -1; \ return SPIFFS_ERR_NOT_MOUNTED; \
} }
#define SPIFFS_API_CHECK_CFG(fs) \ #define SPIFFS_API_CHECK_CFG(fs) \
if (!SPIFFS_CHECK_CFG((fs))) { \ if (!SPIFFS_CHECK_CFG((fs))) { \
(fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; \ (fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; \
return -1; \ return SPIFFS_ERR_NOT_CONFIGURED; \
} }
#define SPIFFS_API_CHECK_RES(fs, res) \ #define SPIFFS_API_CHECK_RES(fs, res) \
if ((res) < SPIFFS_OK) { \ if ((res) < SPIFFS_OK) { \
(fs)->err_code = (res); \ (fs)->err_code = (res); \
return -1; \ return (res); \
} }
#define SPIFFS_API_CHECK_RES_UNLOCK(fs, res) \ #define SPIFFS_API_CHECK_RES_UNLOCK(fs, res) \
if ((res) < SPIFFS_OK) { \ if ((res) < SPIFFS_OK) { \
(fs)->err_code = (res); \ (fs)->err_code = (res); \
SPIFFS_UNLOCK(fs); \ SPIFFS_UNLOCK(fs); \
return -1; \ return (res); \
} }
#define SPIFFS_VALIDATE_OBJIX(ph, objid, spix) \ #define SPIFFS_VALIDATE_OBJIX(ph, objid, spix) \
...@@ -311,6 +319,26 @@ ...@@ -311,6 +319,26 @@
// stop searching at end of all look up pages // stop searching at end of all look up pages
#define SPIFFS_VIS_NO_WRAP (1<<2) #define SPIFFS_VIS_NO_WRAP (1<<2)
#if SPIFFS_HAL_CALLBACK_EXTRA
#define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
(_fs)->cfg.hal_write_f((_fs), (_paddr), (_len), (_src))
#define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
(_fs)->cfg.hal_read_f((_fs), (_paddr), (_len), (_dst))
#define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
(_fs)->cfg.hal_erase_f((_fs), (_paddr), (_len))
#else // SPIFFS_HAL_CALLBACK_EXTRA
#define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
(_fs)->cfg.hal_write_f((_paddr), (_len), (_src))
#define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
(_fs)->cfg.hal_read_f((_paddr), (_len), (_dst))
#define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
(_fs)->cfg.hal_erase_f((_paddr), (_len))
#endif // SPIFFS_HAL_CALLBACK_EXTRA
#if SPIFFS_CACHE #if SPIFFS_CACHE
#define SPIFFS_CACHE_FLAG_DIRTY (1<<0) #define SPIFFS_CACHE_FLAG_DIRTY (1<<0)
...@@ -416,9 +444,14 @@ typedef struct __attribute(( packed )) { ...@@ -416,9 +444,14 @@ typedef struct __attribute(( packed )) {
// object index header page header // object index header page header
typedef struct __attribute(( packed )) typedef struct __attribute(( packed ))
#if SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
__attribute(( aligned(sizeof(spiffs_page_ix)) ))
#endif
{ {
// common page header // common page header
spiffs_page_header p_hdr; spiffs_page_header p_hdr;
// alignment
u8_t _align[4 - ((sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3))];
// size of object // size of object
u32_t size; u32_t size;
// type of object // type of object
...@@ -430,11 +463,12 @@ typedef struct __attribute(( packed )) ...@@ -430,11 +463,12 @@ typedef struct __attribute(( packed ))
// object index page header // object index page header
typedef struct __attribute(( packed )) { typedef struct __attribute(( packed )) {
spiffs_page_header p_hdr; spiffs_page_header p_hdr;
u8_t _align[4 - ((sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3))];
} spiffs_page_object_ix; } spiffs_page_object_ix;
// callback func for object lookup visitor // callback func for object lookup visitor
typedef s32_t (*spiffs_visitor_f)(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry, typedef s32_t (*spiffs_visitor_f)(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry,
u32_t user_data, void *user_p); const void *user_const_p, void *user_var_p);
#if SPIFFS_CACHE #if SPIFFS_CACHE
...@@ -495,8 +529,8 @@ s32_t spiffs_obj_lu_find_entry_visitor( ...@@ -495,8 +529,8 @@ s32_t spiffs_obj_lu_find_entry_visitor(
u8_t flags, u8_t flags,
spiffs_obj_id obj_id, spiffs_obj_id obj_id,
spiffs_visitor_f v, spiffs_visitor_f v,
u32_t user_data, const void *user_const_p,
void *user_p, void *user_var_p,
spiffs_block_ix *block_ix, spiffs_block_ix *block_ix,
int *lu_entry); int *lu_entry);
...@@ -504,6 +538,11 @@ s32_t spiffs_erase_block( ...@@ -504,6 +538,11 @@ s32_t spiffs_erase_block(
spiffs *fs, spiffs *fs,
spiffs_block_ix bix); spiffs_block_ix bix);
#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
s32_t spiffs_probe(
spiffs_config *cfg);
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
// --------------- // ---------------
s32_t spiffs_obj_lu_scan( s32_t spiffs_obj_lu_scan(
...@@ -512,7 +551,7 @@ s32_t spiffs_obj_lu_scan( ...@@ -512,7 +551,7 @@ s32_t spiffs_obj_lu_scan(
s32_t spiffs_obj_lu_find_free_obj_id( s32_t spiffs_obj_lu_find_free_obj_id(
spiffs *fs, spiffs *fs,
spiffs_obj_id *obj_id, spiffs_obj_id *obj_id,
u8_t *conflicting_name); const u8_t *conflicting_name);
s32_t spiffs_obj_lu_find_free( s32_t spiffs_obj_lu_find_free(
spiffs *fs, spiffs *fs,
...@@ -573,7 +612,7 @@ s32_t spiffs_page_delete( ...@@ -573,7 +612,7 @@ s32_t spiffs_page_delete(
s32_t spiffs_object_create( s32_t spiffs_object_create(
spiffs *fs, spiffs *fs,
spiffs_obj_id obj_id, spiffs_obj_id obj_id,
u8_t name[SPIFFS_OBJ_NAME_LEN], const u8_t name[SPIFFS_OBJ_NAME_LEN],
spiffs_obj_type type, spiffs_obj_type type,
spiffs_page_ix *objix_hdr_pix); spiffs_page_ix *objix_hdr_pix);
...@@ -583,7 +622,7 @@ s32_t spiffs_object_update_index_hdr( ...@@ -583,7 +622,7 @@ s32_t spiffs_object_update_index_hdr(
spiffs_obj_id obj_id, spiffs_obj_id obj_id,
spiffs_page_ix objix_hdr_pix, spiffs_page_ix objix_hdr_pix,
u8_t *new_objix_hdr_data, u8_t *new_objix_hdr_data,
u8_t name[SPIFFS_OBJ_NAME_LEN], const u8_t name[SPIFFS_OBJ_NAME_LEN],
u32_t size, u32_t size,
spiffs_page_ix *new_pix); spiffs_page_ix *new_pix);
...@@ -635,7 +674,7 @@ s32_t spiffs_object_truncate( ...@@ -635,7 +674,7 @@ s32_t spiffs_object_truncate(
s32_t spiffs_object_find_object_index_header_by_name( s32_t spiffs_object_find_object_index_header_by_name(
spiffs *fs, spiffs *fs,
u8_t name[SPIFFS_OBJ_NAME_LEN], const u8_t name[SPIFFS_OBJ_NAME_LEN],
spiffs_page_ix *pix); spiffs_page_ix *pix);
// --------------- // ---------------
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment