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_nucleus.h"
#include <string.h>
#if !SPIFFS_READ_ONLY
// Erases a logical block and updates the erase counter.
// If cache is enabled, all pages that might be cached in this block
......@@ -36,7 +39,7 @@ s32_t spiffs_gc_quick(
int cur_entry = 0;
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
fs->stats_gc_runs++;
#endif
......@@ -249,14 +252,12 @@ s32_t spiffs_gc_find_candidate(
memset(fs->work, 0xff, SPIFFS_CFG_LOG_PAGE_SZ(fs));
// 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;
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;
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) {
return res;
}
#endif // !SPIFFS_READ_ONLY
......@@ -7,8 +7,19 @@
#include "spiffs.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);
#endif
#if SPIFFS_BUFFER_HELP
u32_t SPIFFS_buffer_bytes_for_filedescs(spiffs *fs, u32_t num_descs) {
......@@ -26,6 +37,10 @@ u8_t SPIFFS_mounted(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);
if (SPIFFS_CHECK_MOUNT(fs)) {
fs->err_code = SPIFFS_ERR_MOUNTED;
......@@ -49,25 +64,35 @@ s32_t SPIFFS_format(spiffs *fs) {
SPIFFS_UNLOCK(fs);
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,
u8_t *fd_space, u32_t fd_space_size,
void *cache, u32_t cache_size,
spiffs_check_callback check_cb_f) {
void *user_data;
SPIFFS_LOCK(fs);
user_data = fs->user_data;
memset(fs, 0, sizeof(spiffs));
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->work = &work[0];
fs->lu_work = &work[SPIFFS_CFG_LOG_PAGE_SZ(fs)];
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*);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
u8_t addr_lsb = ((u8_t)fd_space) & (ptr_size-1);
#pragma GCC diagnostic pop
u8_t addr_lsb = ((u8_t)(intptr_t)fd_space) & (ptr_size-1);
if (addr_lsb) {
fd_space += (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,
fs->fd_space = fd_space;
fs->fd_count = (fd_space_size/sizeof(spiffs_fd));
// align cache pointer to 4 byte boundary, below is safe
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
addr_lsb = ((u8_t)cache) & (ptr_size-1);
#pragma GCC diagnostic pop
// align cache pointer to 4 byte boundary
addr_lsb = ((u8_t)(intptr_t)cache) & (ptr_size-1);
if (addr_lsb) {
u8_t *cache_8 = (u8_t *)cache;
cache_8 += (ptr_size-addr_lsb);
......@@ -89,9 +111,10 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
if (cache_size & (ptr_size-1)) {
cache_size -= (cache_size & (ptr_size-1));
}
#if SPIFFS_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);
#endif
......@@ -152,43 +175,68 @@ void SPIFFS_clearerr(spiffs *fs) {
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;
SPIFFS_API_CHECK_CFG(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_obj_id obj_id;
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);
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_UNLOCK(fs);
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;
SPIFFS_API_CHECK_CFG(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_fd *fd;
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);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)path, &pix);
if ((flags & SPIFFS_CREAT) == 0) {
res = spiffs_object_find_object_index_header_by_name(fs, (const u8_t*)path, &pix);
if ((flags & SPIFFS_O_CREAT) == 0) {
if (res < SPIFFS_OK) {
spiffs_fd_return(fs, fd->file_nbr);
}
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;
// no need to enter conflicting name here, already looked for it above
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
spiffs_fd_return(fs, fd->file_nbr);
}
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) {
spiffs_fd_return(fs, fd->file_nbr);
}
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
flags &= ~SPIFFS_TRUNC;
flags &= ~SPIFFS_O_TRUNC;
#endif // !SPIFFS_READ_ONLY
} else {
if (res < SPIFFS_OK) {
spiffs_fd_return(fs, fd->file_nbr);
......@@ -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_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);
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 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) {
......@@ -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_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);
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 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) {
......@@ -266,14 +365,21 @@ s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
spiffs_fd *fd;
s32_t res;
fh = SPIFFS_FH_UNOFFS(fs, fh);
res = spiffs_fd_get(fs, fh, &fd);
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;
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
spiffs_fflush_cache(fs, fh);
#endif
......@@ -305,6 +411,7 @@ s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t 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) {
(void)fs;
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
return len;
}
#endif // !SPIFFS_READ_ONLY
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_MOUNT(fs);
SPIFFS_LOCK(fs);
......@@ -336,14 +448,19 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
s32_t res;
u32_t offset;
fh = SPIFFS_FH_UNOFFS(fs, fh);
res = spiffs_fd_get(fs, fh, &fd);
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;
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;
#if SPIFFS_CACHE_WR
......@@ -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);
}
#endif
if (fd->flags & SPIFFS_APPEND) {
if (fd->flags & SPIFFS_O_APPEND) {
if (fd->size == SPIFFS_UNDEFINED_LEN) {
offset = 0;
} else {
......@@ -366,7 +483,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
}
#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)) {
// small write, try to cache it
u8_t alloc_cpage = 1;
......@@ -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),
fd->cache_page->offset, fd->cache_page->size);
spiffs_cache_fd_release(fs, fd->cache_page);
SPIFFS_API_CHECK_RES(fs, res);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
} else {
// writing within cache
alloc_cpage = 0;
......@@ -414,7 +531,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
return len;
} else {
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;
SPIFFS_UNLOCK(fs);
return res;
......@@ -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),
fd->cache_page->offset, fd->cache_page->size);
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);
SPIFFS_API_CHECK_RES(fs, res);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
}
}
}
#endif
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;
SPIFFS_UNLOCK(fs);
return res;
#endif // SPIFFS_READ_ONLY
}
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;
s32_t res;
fh = SPIFFS_FH_UNOFFS(fs, fh);
res = spiffs_fd_get(fs, fh, &fd);
SPIFFS_API_CHECK_RES(fs, res);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
#if SPIFFS_CACHE_WR
spiffs_fflush_cache(fs, fh);
......@@ -469,7 +588,7 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
break;
}
if (offs > (s32_t)fd->size) {
if ((offs > (s32_t)fd->size) && (SPIFFS_UNDEFINED_LEN != fd->size)) {
res = SPIFFS_ERR_END_OF_OBJECT;
}
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) {
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_MOUNT(fs);
if (strlen(path) > SPIFFS_OBJ_NAME_LEN - 1) {
SPIFFS_API_CHECK_RES(fs, SPIFFS_ERR_NAME_TOO_LONG);
}
SPIFFS_LOCK(fs);
spiffs_fd *fd;
......@@ -503,7 +629,7 @@ s32_t SPIFFS_remove(spiffs *fs, char *path) {
res = spiffs_fd_find_new(fs, &fd);
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) {
spiffs_fd_return(fs, fd->file_nbr);
}
......@@ -523,19 +649,25 @@ s32_t SPIFFS_remove(spiffs *fs, char *path) {
SPIFFS_UNLOCK(fs);
return 0;
#endif // SPIFFS_READ_ONLY
}
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_MOUNT(fs);
SPIFFS_LOCK(fs);
spiffs_fd *fd;
s32_t res;
fh = SPIFFS_FH_UNOFFS(fs, fh);
res = spiffs_fd_get(fs, fh, &fd);
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;
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
}
......@@ -551,9 +683,11 @@ s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) {
SPIFFS_UNLOCK(fs);
return 0;
#endif // SPIFFS_READ_ONLY
}
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_obj_id obj_id;
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
obj_id_addr, sizeof(spiffs_obj_id), (u8_t *)&obj_id);
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->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);
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_MOUNT(fs);
if (strlen(path) > SPIFFS_OBJ_NAME_LEN - 1) {
SPIFFS_API_CHECK_RES(fs, SPIFFS_ERR_NAME_TOO_LONG);
}
SPIFFS_LOCK(fs);
s32_t res;
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);
res = spiffs_stat_pix(fs, pix, 0, s);
......@@ -600,6 +738,7 @@ s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) {
spiffs_fd *fd;
s32_t res;
fh = SPIFFS_FH_UNOFFS(fs, fh);
res = spiffs_fd_get(fs, fh, &fd);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
......@@ -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
// given filehandle. If so, these writes are flushed.
#if SPIFFS_CACHE == 1
static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) {
(void)fs;
(void)fh;
s32_t res = SPIFFS_OK;
#if SPIFFS_CACHE_WR
#if !SPIFFS_READ_ONLY && SPIFFS_CACHE_WR
spiffs_fd *fd;
res = spiffs_fd_get(fs, fh, &fd);
SPIFFS_API_CHECK_RES(fs, res);
if ((fd->flags & SPIFFS_DIRECT) == 0) {
if ((fd->flags & SPIFFS_O_DIRECT) == 0) {
if (fd->cache_page == 0) {
// see if object id is associated with cache already
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) {
return res;
}
#endif
s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) {
(void)fh;
SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs);
s32_t res = SPIFFS_OK;
#if SPIFFS_CACHE_WR
#if !SPIFFS_READ_ONLY && SPIFFS_CACHE_WR
SPIFFS_LOCK(fs);
fh = SPIFFS_FH_UNOFFS(fs, fh);
res = spiffs_fflush_cache(fs, fh);
SPIFFS_API_CHECK_RES_UNLOCK(fs,res);
SPIFFS_UNLOCK(fs);
......@@ -660,38 +805,46 @@ s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) {
return res;
}
void SPIFFS_close(spiffs *fs, spiffs_file fh) {
if (!SPIFFS_CHECK_CFG((fs))) {
(fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED;
return;
}
s32_t SPIFFS_close(spiffs *fs, spiffs_file fh) {
SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs);
if (!SPIFFS_CHECK_MOUNT(fs)) {
fs->err_code = SPIFFS_ERR_NOT_MOUNTED;
return;
}
s32_t res = SPIFFS_OK;
SPIFFS_LOCK(fs);
fh = SPIFFS_FH_UNOFFS(fs, fh);
#if SPIFFS_CACHE
spiffs_fflush_cache(fs, fh);
res = spiffs_fflush_cache(fs, fh);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
#endif
spiffs_fd_return(fs, fh);
res = spiffs_fd_return(fs, fh);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
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_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_page_ix pix_old, pix_dummy;
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);
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) {
res = SPIFFS_OK;
} else if (res == SPIFFS_OK) {
......@@ -708,7 +861,7 @@ s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) {
}
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);
spiffs_fd_return(fs, fd->file_nbr);
......@@ -718,9 +871,10 @@ s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) {
SPIFFS_UNLOCK(fs);
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;
if (!SPIFFS_CHECK_CFG((fs))) {
......@@ -744,9 +898,9 @@ static s32_t spiffs_read_dir_v(
spiffs_obj_id obj_id,
spiffs_block_ix bix,
int ix_entry,
u32_t user_data,
void *user_p) {
(void)user_data;
const void *user_const_p,
void *user_var_p) {
(void)user_const_p;
s32_t res;
spiffs_page_object_ix_header objix_hdr;
if (obj_id == SPIFFS_OBJ_ID_FREE || obj_id == SPIFFS_OBJ_ID_DELETED ||
......@@ -762,10 +916,9 @@ static s32_t spiffs_read_dir_v(
objix_hdr.p_hdr.span_ix == 0 &&
(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)) {
struct spiffs_dirent *e = (struct spiffs_dirent *)user_p;
struct spiffs_dirent *e = (struct spiffs_dirent*)user_var_p;
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->size = objix_hdr.size == SPIFFS_UNDEFINED_LEN ? 0 : objix_hdr.size;
e->pix = pix;
......@@ -780,7 +933,7 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) {
d->fs->err_code = SPIFFS_ERR_NOT_MOUNTED;
return 0;
}
SPIFFS_LOCK(fs);
SPIFFS_LOCK(d->fs);
spiffs_block_ix bix;
int entry;
......@@ -804,7 +957,7 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) {
} else {
d->fs->err_code = res;
}
SPIFFS_UNLOCK(fs);
SPIFFS_UNLOCK(d->fs);
return ret;
}
......@@ -815,6 +968,10 @@ s32_t SPIFFS_closedir(spiffs_DIR *d) {
}
s32_t SPIFFS_check(spiffs *fs) {
#if SPIFFS_READ_ONLY
(void)fs;
return SPIFFS_ERR_RO_NOT_IMPL;
#else
s32_t res;
SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs);
......@@ -830,6 +987,7 @@ s32_t SPIFFS_check(spiffs *fs) {
SPIFFS_UNLOCK(fs);
return res;
#endif // SPIFFS_READ_ONLY
}
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;
}
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_LOCK(fs);
spiffs_fd *fd;
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;
res = spiffs_gc_quick(fs, max_free_pages);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
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;
res = spiffs_fd_get(fs, fh, &fd);
SPIFFS_API_CHECK_RES(fs, res);
#if SPIFFS_CACHE_WR
spiffs_fflush_cache(fs, fh);
#endif
SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs);
SPIFFS_LOCK(fs);
res = (fd->fdoffset == fd->size);
res = spiffs_gc_check(fs, size);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
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_LOCK(fs);
fh = SPIFFS_FH_UNOFFS(fs, fh);
spiffs_fd *fd;
s32_t res;
res = spiffs_fd_get(fs, fh, &fd);
SPIFFS_API_CHECK_RES(fs, res);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
#if SPIFFS_CACHE_WR
spiffs_fflush_cache(fs, fh);
res = spiffs_fflush_cache(fs, fh);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
#endif
res = fd->size;
res = (fd->fdoffset >= (fd->size == SPIFFS_UNDEFINED_LEN ? 0 : fd->size));
SPIFFS_UNLOCK(fs);
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;
SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(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_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) {
s32_t res;
SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs);
SPIFFS_LOCK(fs);
res = fd->fdoffset;
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);
return 0;
}
#if SPIFFS_TEST_VISUALISATION
s32_t SPIFFS_vis(spiffs *fs) {
s32_t res = SPIFFS_OK;
......@@ -1008,11 +1171,10 @@ s32_t SPIFFS_vis(spiffs *fs) {
spiffs_printf("free_blocks: %i\n", fs->free_blocks);
spiffs_printf("page_alloc: %i\n", fs->stats_p_allocated);
spiffs_printf("page_delet: %i\n", fs->stats_p_deleted);
SPIFFS_UNLOCK(fs);
u32_t total, used;
SPIFFS_info(fs, &total, &used);
spiffs_printf("used: %i of %i\n", used, total);
SPIFFS_UNLOCK(fs);
return res;
}
#endif
#include "spiffs.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) {
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
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) {
s32_t res = SPIFFS_OK;
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
#endif
return res;
}
#endif // !SPIFFS_READ_ONLY
#if !SPIFFS_CACHE
......@@ -64,7 +67,7 @@ s32_t spiffs_phys_rd(
u32_t addr,
u32_t len,
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(
......@@ -72,17 +75,19 @@ s32_t spiffs_phys_wr(
u32_t addr,
u32_t len,
u8_t *src) {
return fs->cfg.hal_write_f(addr, len, src);
return SPIFFS_HAL_WRITE(fs, addr, len, src);
}
#endif
#if !SPIFFS_READ_ONLY
s32_t spiffs_phys_cpy(
spiffs *fs,
spiffs_file fh,
u32_t dst,
u32_t src,
u32_t len) {
(void)fh;
s32_t res;
u8_t b[SPIFFS_COPY_BUFFER_STACK];
while (len > 0) {
......@@ -97,10 +102,11 @@ s32_t spiffs_phys_cpy(
}
return SPIFFS_OK;
}
#endif // !SPIFFS_READ_ONLY
// 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.
// 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
// 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.
......@@ -112,8 +118,8 @@ s32_t spiffs_phys_cpy(
// SPIFFS_VIS_NO_WRAP
// @param obj_id argument object id
// @param v visitor callback function
// @param user_data any data, passed to the callback visitor function
// @param user_p any pointer, passed to the callback visitor function
// @param user_const_p any const 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 lu_entry reported look up index where match was found
s32_t spiffs_obj_lu_find_entry_visitor(
......@@ -123,8 +129,8 @@ s32_t spiffs_obj_lu_find_entry_visitor(
u8_t flags,
spiffs_obj_id obj_id,
spiffs_visitor_f v,
u32_t user_data,
void *user_p,
const void *user_const_p,
void *user_var_p,
spiffs_block_ix *block_ix,
int *lu_entry) {
s32_t res = SPIFFS_OK;
......@@ -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],
cur_block,
cur_entry,
user_data,
user_p);
user_const_p,
user_var_p);
if (res == SPIFFS_VIS_COUNTINUE || res == SPIFFS_VIS_COUNTINUE_RELOAD) {
if (res == SPIFFS_VIS_COUNTINUE_RELOAD) {
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(
return SPIFFS_VIS_END;
}
#if !SPIFFS_READ_ONLY
s32_t spiffs_erase_block(
spiffs *fs,
spiffs_block_ix bix) {
......@@ -227,7 +234,8 @@ s32_t spiffs_erase_block(
// here we ignore res, just try erasing the block
while (size > 0) {
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);
size -= SPIFFS_CFG_PHYS_ERASE_SZ(fs);
}
......@@ -241,7 +249,7 @@ s32_t spiffs_erase_block(
#if SPIFFS_USE_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,
SPIFFS_MAGIC_PADDR(fs, bix),
sizeof(spiffs_obj_id), (u8_t *)&magic);
......@@ -255,6 +263,59 @@ s32_t spiffs_erase_block(
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(
......@@ -262,11 +323,11 @@ static s32_t spiffs_obj_lu_scan_v(
spiffs_obj_id obj_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)bix;
(void)user_data;
(void)user_p;
(void)user_const_p;
(void)user_var_p;
if (obj_id == SPIFFS_OBJ_ID_FREE) {
if (ix_entry == 0) {
fs->free_blocks++;
......@@ -309,7 +370,7 @@ s32_t spiffs_obj_lu_scan(
sizeof(spiffs_obj_id), (u8_t *)&magic);
SPIFFS_CHECK_RES(res);
if (magic != SPIFFS_MAGIC(fs)) {
if (magic != SPIFFS_MAGIC(fs, bix)) {
if (unerased_bix == (spiffs_block_ix)-1) {
// allow one unerased block as it might be powered down during an erase
unerased_bix = bix;
......@@ -348,7 +409,11 @@ s32_t spiffs_obj_lu_scan(
if (unerased_bix != (spiffs_block_ix)-1) {
// found one unerased block, remedy
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);
#endif // SPIFFS_READ_ONLY
SPIFFS_CHECK_RES(res);
}
#endif
......@@ -379,6 +444,7 @@ s32_t spiffs_obj_lu_scan(
return res;
}
#if !SPIFFS_READ_ONLY
// Find free object lookup entry
// Iterate over object lookup pages in each block until a free object id entry is found
s32_t spiffs_obj_lu_find_free(
......@@ -407,12 +473,13 @@ s32_t spiffs_obj_lu_find_free(
fs->free_blocks--;
}
}
if (res == SPIFFS_VIS_END) {
if (res == SPIFFS_ERR_FULL) {
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
// 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(
spiffs_obj_id obj_id,
spiffs_block_ix bix,
int ix_entry,
u32_t user_data,
void *user_p) {
const void *user_const_p,
void *user_var_p) {
s32_t res;
spiffs_page_header ph;
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(
SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_header), (u8_t *)&ph);
SPIFFS_CHECK_RES(res);
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 &&
!((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;
} else {
return SPIFFS_VIS_COUNTINUE;
......@@ -474,8 +541,8 @@ s32_t spiffs_obj_lu_find_id_and_span(
SPIFFS_VIS_CHECK_ID,
obj_id,
spiffs_obj_lu_find_id_and_span_v,
(u32_t)spix,
exclusion_pix ? &exclusion_pix : 0,
&spix,
&bix,
&entry);
......@@ -513,8 +580,8 @@ s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
SPIFFS_VIS_CHECK_PH,
obj_id,
spiffs_obj_lu_find_id_and_span_v,
(u32_t)spix,
exclusion_pix ? &exclusion_pix : 0,
&spix,
&bix,
&entry);
......@@ -534,6 +601,7 @@ s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
return res;
}
#if !SPIFFS_READ_ONLY
// Allocates a free defined page with given obj_id
// Occupies object lookup entry and page
// 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(
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.
// If page data is null, provided header is used for metainfo and page data is physically copied.
s32_t spiffs_page_move(
......@@ -654,7 +724,9 @@ s32_t spiffs_page_move(
res = spiffs_page_delete(fs, src_pix);
return res;
}
#endif // !SPIFFS_READ_ONLY
#if !SPIFFS_READ_ONLY
// Deletes a page and removes it from object lookup.
s32_t spiffs_page_delete(
spiffs *fs,
......@@ -683,12 +755,14 @@ s32_t spiffs_page_delete(
return res;
}
#endif // !SPIFFS_READ_ONLY
#if !SPIFFS_READ_ONLY
// Create an object index header page with empty index and undefined length
s32_t spiffs_object_create(
spiffs *fs,
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_page_ix *objix_hdr_pix) {
s32_t res = SPIFFS_OK;
......@@ -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.type = type;
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
......@@ -735,7 +809,9 @@ s32_t spiffs_object_create(
return res;
}
#endif // !SPIFFS_READ_ONLY
#if !SPIFFS_READ_ONLY
// 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
// name may be null, if so name is not changed
......@@ -746,7 +822,7 @@ s32_t spiffs_object_update_index_hdr(
spiffs_obj_id obj_id,
spiffs_page_ix objix_hdr_pix,
u8_t *new_objix_hdr_data,
u8_t name[SPIFFS_OBJ_NAME_LEN],
const u8_t name[SPIFFS_OBJ_NAME_LEN],
u32_t size,
spiffs_page_ix *new_pix) {
s32_t res = SPIFFS_OK;
......@@ -770,7 +846,7 @@ s32_t spiffs_object_update_index_hdr(
// change 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) {
objix_hdr->size = size;
......@@ -790,18 +866,19 @@ s32_t spiffs_object_update_index_hdr(
return res;
}
#endif // !SPIFFS_READ_ONLY
void spiffs_cb_object_event(
spiffs *fs,
spiffs_fd *fd,
int ev,
spiffs_obj_id obj_id,
spiffs_obj_id obj_id_raw,
spiffs_span_ix spix,
spiffs_page_ix new_pix,
u32_t new_size) {
(void)fd;
// 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;
spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
for (i = 0; i < fs->fd_count; i++) {
......@@ -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
......@@ -886,6 +979,7 @@ s32_t spiffs_object_open_by_page(
return res;
}
#if !SPIFFS_READ_ONLY
// Append to object
// 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) {
......@@ -1125,8 +1219,10 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
}
return res;
}
} // spiffs_object_append
#endif // !SPIFFS_READ_ONLY
#if !SPIFFS_READ_ONLY
// Modify object
// 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) {
......@@ -1326,16 +1422,17 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
}
return res;
}
} // spiffs_object_modify
#endif // !SPIFFS_READ_ONLY
static s32_t spiffs_object_find_object_index_header_by_name_v(
spiffs *fs,
spiffs_obj_id obj_id,
spiffs_block_ix bix,
int ix_entry,
u32_t user_data,
void *user_p) {
(void)user_data;
const void *user_const_p,
void *user_var_p) {
(void)user_var_p;
s32_t res;
spiffs_page_object_ix_header objix_hdr;
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(
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)) ==
(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;
}
}
......@@ -1360,7 +1457,7 @@ static s32_t spiffs_object_find_object_index_header_by_name_v(
// Finds object index header page by name
s32_t spiffs_object_find_object_index_header_by_name(
spiffs *fs,
u8_t name[SPIFFS_OBJ_NAME_LEN],
const u8_t name[SPIFFS_OBJ_NAME_LEN],
spiffs_page_ix *pix) {
s32_t res;
spiffs_block_ix bix;
......@@ -1372,8 +1469,8 @@ s32_t spiffs_object_find_object_index_header_by_name(
0,
0,
spiffs_object_find_object_index_header_by_name_v,
0,
name,
0,
&bix,
&entry);
......@@ -1392,6 +1489,7 @@ s32_t spiffs_object_find_object_index_header_by_name(
return res;
}
#if !SPIFFS_READ_ONLY
// Truncates object to new size. If new size is null, object may be removed totally
s32_t spiffs_object_truncate(
spiffs_fd *fd,
......@@ -1400,8 +1498,16 @@ s32_t spiffs_object_truncate(
s32_t res = SPIFFS_OK;
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_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);
......@@ -1440,11 +1546,18 @@ s32_t spiffs_object_truncate(
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);
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);
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
fd->objix_hdr_pix, 0, 0, cur_size, &new_objix_hdr_pix);
SPIFFS_CHECK_RES(res);
}
fd->size = cur_size;
}
}
......@@ -1480,7 +1593,7 @@ s32_t spiffs_object_truncate(
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
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) {
......@@ -1611,7 +1724,8 @@ s32_t spiffs_object_truncate(
fd->size = cur_size;
return res;
}
} // spiffs_object_truncate
#endif // !SPIFFS_READ_ONLY
s32_t spiffs_object_read(
spiffs_fd *fd,
......@@ -1691,6 +1805,7 @@ s32_t spiffs_object_read(
return res;
}
#if !SPIFFS_READ_ONLY
typedef struct {
spiffs_obj_id min_obj_id;
spiffs_obj_id max_obj_id;
......@@ -1699,10 +1814,10 @@ typedef struct {
} 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,
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) {
spiffs_obj_id min_obj_id = user_data;
u8_t *conflicting_name = (u8_t *)user_p;
spiffs_obj_id min_obj_id = *((spiffs_obj_id*)user_var_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 && (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
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)) ==
(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;
}
}
......@@ -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,
u32_t user_data, void *user_p) {
(void)user_data;
const void *user_const_p, void *user_var_p) {
(void)user_var_p;
if (id != SPIFFS_OBJ_ID_FREE && id != SPIFFS_OBJ_ID_DELETED && (id & SPIFFS_OBJ_ID_IX_FLAG)) {
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;
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
((objix_hdr.p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET)) ==
(SPIFFS_PH_FLAG_DELET))) {
// 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;
}
......@@ -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
// 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.
// Finally, the bitmasked 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) {
// 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, const u8_t *conflicting_name) {
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_obj_id free_obj_id = SPIFFS_OBJ_ID_FREE;
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
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));
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,
conflicting_name, 0, 0);
res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_obj_lu_find_free_obj_id_bitmap_v,
conflicting_name, &state.min_obj_id, 0, 0);
if (res == SPIFFS_VIS_END) res = SPIFFS_OK;
SPIFFS_CHECK_RES(res);
// 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
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));
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;
SPIFFS_CHECK_RES(res);
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
return res;
}
#endif // !SPIFFS_READ_ONLY
s32_t spiffs_fd_find_new(spiffs *fs, spiffs_fd **fd) {
u32_t i;
......
......@@ -131,7 +131,15 @@
#define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0)
#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)
......@@ -264,26 +272,26 @@
#define SPIFFS_API_CHECK_MOUNT(fs) \
if (!SPIFFS_CHECK_MOUNT((fs))) { \
(fs)->err_code = SPIFFS_ERR_NOT_MOUNTED; \
return -1; \
return SPIFFS_ERR_NOT_MOUNTED; \
}
#define SPIFFS_API_CHECK_CFG(fs) \
if (!SPIFFS_CHECK_CFG((fs))) { \
(fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; \
return -1; \
return SPIFFS_ERR_NOT_CONFIGURED; \
}
#define SPIFFS_API_CHECK_RES(fs, res) \
if ((res) < SPIFFS_OK) { \
(fs)->err_code = (res); \
return -1; \
return (res); \
}
#define SPIFFS_API_CHECK_RES_UNLOCK(fs, res) \
if ((res) < SPIFFS_OK) { \
(fs)->err_code = (res); \
SPIFFS_UNLOCK(fs); \
return -1; \
return (res); \
}
#define SPIFFS_VALIDATE_OBJIX(ph, objid, spix) \
......@@ -311,6 +319,26 @@
// stop searching at end of all look up pages
#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
#define SPIFFS_CACHE_FLAG_DIRTY (1<<0)
......@@ -416,9 +444,14 @@ typedef struct __attribute(( packed )) {
// object index header page header
typedef struct __attribute(( packed ))
#if SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
__attribute(( aligned(sizeof(spiffs_page_ix)) ))
#endif
{
// common page header
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
u32_t size;
// type of object
......@@ -430,11 +463,12 @@ typedef struct __attribute(( packed ))
// object index page header
typedef struct __attribute(( packed )) {
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;
// 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,
u32_t user_data, void *user_p);
const void *user_const_p, void *user_var_p);
#if SPIFFS_CACHE
......@@ -495,8 +529,8 @@ s32_t spiffs_obj_lu_find_entry_visitor(
u8_t flags,
spiffs_obj_id obj_id,
spiffs_visitor_f v,
u32_t user_data,
void *user_p,
const void *user_const_p,
void *user_var_p,
spiffs_block_ix *block_ix,
int *lu_entry);
......@@ -504,6 +538,11 @@ s32_t spiffs_erase_block(
spiffs *fs,
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(
......@@ -512,7 +551,7 @@ s32_t spiffs_obj_lu_scan(
s32_t spiffs_obj_lu_find_free_obj_id(
spiffs *fs,
spiffs_obj_id *obj_id,
u8_t *conflicting_name);
const u8_t *conflicting_name);
s32_t spiffs_obj_lu_find_free(
spiffs *fs,
......@@ -573,7 +612,7 @@ s32_t spiffs_page_delete(
s32_t spiffs_object_create(
spiffs *fs,
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_page_ix *objix_hdr_pix);
......@@ -583,7 +622,7 @@ s32_t spiffs_object_update_index_hdr(
spiffs_obj_id obj_id,
spiffs_page_ix objix_hdr_pix,
u8_t *new_objix_hdr_data,
u8_t name[SPIFFS_OBJ_NAME_LEN],
const u8_t name[SPIFFS_OBJ_NAME_LEN],
u32_t size,
spiffs_page_ix *new_pix);
......@@ -635,7 +674,7 @@ s32_t spiffs_object_truncate(
s32_t spiffs_object_find_object_index_header_by_name(
spiffs *fs,
u8_t name[SPIFFS_OBJ_NAME_LEN],
const u8_t name[SPIFFS_OBJ_NAME_LEN],
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