Grabbed latest spiffs + vfs layer from dev branch.
Also included the recent LVM fix. Platform flash layer not yet functional.
This commit is contained in:
parent
fe602d2d7e
commit
4f1b33d522
|
@ -12,9 +12,9 @@
|
|||
#include "platform.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "flash_fs.h"
|
||||
#include "flash_api.h"
|
||||
#include "vfs.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_system.h"
|
||||
|
||||
#include "driver/console.h"
|
||||
#include "task/task.h"
|
||||
|
@ -62,23 +62,12 @@ void nodemcu_init(void)
|
|||
return;
|
||||
}
|
||||
|
||||
// FIXME: this breaks horribly on the ESP32 at the moment; possibly all flash writes?
|
||||
#if defined(FLASH_SAFE_API) && defined(__ESP8266__)
|
||||
if( flash_safe_get_size_byte() != flash_rom_get_size_byte()) {
|
||||
#if defined(FLASH_SAFE_API)
|
||||
if (flash_safe_get_size_byte() != flash_rom_get_size_byte()) {
|
||||
NODE_ERR("Self adjust flash size.\n");
|
||||
// Fit hardware real flash size.
|
||||
flash_rom_set_size_byte(flash_safe_get_size_byte());
|
||||
|
||||
if( !fs_format() )
|
||||
{
|
||||
NODE_ERR( "\ni*** ERROR ***: unable to format. FS might be compromised.\n" );
|
||||
NODE_ERR( "It is advised to re-flash the NodeMCU image.\n" );
|
||||
}
|
||||
else{
|
||||
NODE_ERR( "format done.\n" );
|
||||
}
|
||||
fs_unmount(); // mounted by format.
|
||||
|
||||
// Reboot to get SDK to use (or write) init data at new location
|
||||
system_restart ();
|
||||
|
||||
|
@ -87,9 +76,16 @@ void nodemcu_init(void)
|
|||
}
|
||||
#endif // defined(FLASH_SAFE_API)
|
||||
|
||||
#if defined ( BUILD_SPIFFS )
|
||||
fs_mount();
|
||||
// test_spiffs();
|
||||
#if defined ( CONFIG_BUILD_SPIFFS )
|
||||
if (!vfs_mount("/FLASH", 0)) {
|
||||
// Failed to mount -- try reformat
|
||||
NODE_ERR("Formatting file system. Please wait...\n");
|
||||
if (1 || !vfs_format()) { // FIXME
|
||||
NODE_ERR( "*** ERROR ***: unable to format. FS might be compromised.\n" );
|
||||
NODE_ERR( "It is advised to re-flash the NodeMCU image.\n" );
|
||||
}
|
||||
// Note that fs_format leaves the file system mounted
|
||||
}
|
||||
#endif
|
||||
|
||||
task_post_low(task_get_id(start_lua), 0);
|
||||
|
@ -120,5 +116,5 @@ void app_main (void)
|
|||
console_init (&cfg, input_task);
|
||||
|
||||
xTaskCreate (
|
||||
nodemcu_main, "nodemcu", 2048, 0, configTIMER_TASK_PRIORITY +1, NULL);
|
||||
nodemcu_main, "nodemcu", 2560, 0, tskIDLE_PRIORITY +1, NULL);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include C_HEADER_STDLIB
|
||||
#include C_HEADER_STRING
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
#include "flash_fs.h"
|
||||
#include "vfs.h"
|
||||
#else
|
||||
#endif
|
||||
|
||||
|
@ -671,8 +671,8 @@ static const char *getFSF (lua_State *L, void *ud, size_t *size) {
|
|||
return "\n";
|
||||
}
|
||||
|
||||
if (fs_eof(lf->f)) return NULL;
|
||||
*size = fs_read(lf->f, lf->buff, sizeof(lf->buff));
|
||||
if (vfs_eof(lf->f)) return NULL;
|
||||
*size = vfs_read(lf->f, lf->buff, sizeof(lf->buff));
|
||||
|
||||
return (*size > 0) ? lf->buff : NULL;
|
||||
}
|
||||
|
@ -697,29 +697,29 @@ LUALIB_API int luaL_loadfsfile (lua_State *L, const char *filename) {
|
|||
}
|
||||
else {
|
||||
lua_pushfstring(L, "@%s", filename);
|
||||
lf.f = fs_open(filename, FS_RDONLY);
|
||||
if (lf.f < FS_OPEN_OK) return errfsfile(L, "open", fnameindex);
|
||||
lf.f = vfs_open(filename, "r");
|
||||
if (!lf.f) return errfsfile(L, "open", fnameindex);
|
||||
}
|
||||
// if(fs_size(lf.f)>LUAL_BUFFERSIZE)
|
||||
// if(vfs_size(lf.f)>LUAL_BUFFERSIZE)
|
||||
// return luaL_error(L, "file is too big");
|
||||
c = fs_getc(lf.f);
|
||||
c = vfs_getc(lf.f);
|
||||
if (c == '#') { /* Unix exec. file? */
|
||||
lf.extraline = 1;
|
||||
while ((c = fs_getc(lf.f)) != EOF && c != '\n') ; /* skip first line */
|
||||
if (c == '\n') c = fs_getc(lf.f);
|
||||
while ((c = vfs_getc(lf.f)) != EOF && c != '\n') ; /* skip first line */
|
||||
if (c == '\n') c = vfs_getc(lf.f);
|
||||
}
|
||||
if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
|
||||
fs_close(lf.f);
|
||||
lf.f = fs_open(filename, FS_RDONLY); /* reopen in binary mode */
|
||||
if (lf.f < FS_OPEN_OK) return errfsfile(L, "reopen", fnameindex);
|
||||
vfs_close(lf.f);
|
||||
lf.f = vfs_open(filename, "r"); /* reopen in binary mode */
|
||||
if (!lf.f) return errfsfile(L, "reopen", fnameindex);
|
||||
/* skip eventual `#!...' */
|
||||
while ((c = fs_getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;
|
||||
while ((c = vfs_getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;
|
||||
lf.extraline = 0;
|
||||
}
|
||||
fs_ungetc(c, lf.f);
|
||||
vfs_ungetc(c, lf.f);
|
||||
status = lua_load(L, getFSF, &lf, lua_tostring(L, -1));
|
||||
|
||||
if (filename) fs_close(lf.f); /* close file (even in case of errors) */
|
||||
if (filename) vfs_close(lf.f); /* close file (even in case of errors) */
|
||||
lua_remove(L, fnameindex);
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "flash_fs.h"
|
||||
#include "vfs.h"
|
||||
|
||||
#define liolib_c
|
||||
#define LUA_LIB
|
||||
|
@ -39,7 +39,7 @@ static const int liolib_keys[] = {(int)&luaL_callmeta, (int)&luaL_typerror, (int
|
|||
static const char *const fnames[] = {"input", "output"};
|
||||
|
||||
static int pushresult (lua_State *L, int i, const char *filename) {
|
||||
int en = fs_error(0); /* calls to Lua API may change this value */
|
||||
int en = vfs_ferrno(0); /* calls to Lua API may change this value */
|
||||
if (i) {
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
|
@ -57,7 +57,7 @@ static int pushresult (lua_State *L, int i, const char *filename) {
|
|||
|
||||
|
||||
static void fileerror (lua_State *L, int arg, const char *filename) {
|
||||
lua_pushfstring(L, "%s: err(%d)", filename, fs_error(0));
|
||||
lua_pushfstring(L, "%s: err(%d)", filename, vfs_ferrno(0));
|
||||
luaL_argerror(L, arg, lua_tostring(L, -1));
|
||||
}
|
||||
|
||||
|
@ -130,7 +130,7 @@ static int io_pclose (lua_State *L) {
|
|||
*/
|
||||
static int io_fclose (lua_State *L) {
|
||||
int *p = tofilep(L);
|
||||
int ok = (fs_close(*p) == 0);
|
||||
int ok = (vfs_close(*p) == 0);
|
||||
*p = FS_OPEN_OK - 1;
|
||||
return pushresult(L, ok, NULL);
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ static int aux_close (lua_State *L) {
|
|||
lua_pushliteral(L, "cannot close standard file");
|
||||
return 2;
|
||||
}
|
||||
int ok = (fs_close(*p) == 0);
|
||||
int ok = (vfs_close(*p) == 0);
|
||||
*p = FS_OPEN_OK - 1;
|
||||
return pushresult(L, ok, NULL);
|
||||
#endif
|
||||
|
@ -187,7 +187,7 @@ static int io_open (lua_State *L) {
|
|||
const char *filename = luaL_checkstring(L, 1);
|
||||
const char *mode = luaL_optstring(L, 2, "r");
|
||||
int *pf = newfile(L);
|
||||
*pf = fs_open(filename, fs_mode2flag(mode));
|
||||
*pf = vfs_open(filename, mode);
|
||||
return (*pf == FS_OPEN_OK - 1) ? pushresult(L, 0, filename) : 1;
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,7 @@ static int io_popen (lua_State *L) {
|
|||
const char *filename = luaL_checkstring(L, 1);
|
||||
const char *mode = luaL_optstring(L, 2, "r");
|
||||
int *pf = newfile(L);
|
||||
*pf = lua_popen(L, filename, fs_mode2flag(mode));
|
||||
*pf = lua_popen(L, filename, mode);
|
||||
return (*pf == FS_OPEN_OK - 1) ? pushresult(L, 0, filename) : 1;
|
||||
}
|
||||
|
||||
|
@ -230,7 +230,7 @@ static int g_iofile (lua_State *L, int f, const char *mode) {
|
|||
const char *filename = lua_tostring(L, 1);
|
||||
if (filename) {
|
||||
int *pf = newfile(L);
|
||||
*pf = fs_open(filename, fs_mode2flag(mode));
|
||||
*pf = vfs_open(filename, mode);
|
||||
if (*pf == FS_OPEN_OK - 1)
|
||||
fileerror(L, 1, filename);
|
||||
}
|
||||
|
@ -282,7 +282,7 @@ static int io_lines (lua_State *L) {
|
|||
else {
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
int *pf = newfile(L);
|
||||
*pf = fs_open(filename, FS_RDONLY);
|
||||
*pf = vfs_open(filename, "r");
|
||||
if (*pf == FS_OPEN_OK - 1)
|
||||
fileerror(L, 1, filename);
|
||||
aux_lines(L, lua_gettop(L), 1);
|
||||
|
@ -300,7 +300,7 @@ static int io_lines (lua_State *L) {
|
|||
#if 0
|
||||
static int read_number (lua_State *L, int f) {
|
||||
lua_Number d;
|
||||
if (fs_scanf(f, LUA_NUMBER_SCAN, &d) == 1) {
|
||||
if (vfs_scanf(f, LUA_NUMBER_SCAN, &d) == 1) {
|
||||
lua_pushnumber(L, d);
|
||||
return 1;
|
||||
}
|
||||
|
@ -312,8 +312,8 @@ static int read_number (lua_State *L, int f) {
|
|||
#endif
|
||||
|
||||
static int test_eof (lua_State *L, int f) {
|
||||
int c = fs_getc(f);
|
||||
fs_ungetc(c, f);
|
||||
int c = vfs_getc(f);
|
||||
vfs_ungetc(c, f);
|
||||
lua_pushlstring(L, NULL, 0);
|
||||
return (c != EOF);
|
||||
}
|
||||
|
@ -325,7 +325,7 @@ static int read_line (lua_State *L, int f) {
|
|||
for (;;) {
|
||||
size_t l;
|
||||
char *p = luaL_prepbuffer(&b);
|
||||
if (fs_gets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */
|
||||
if (vfs_gets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */
|
||||
luaL_pushresult(&b); /* close buffer */
|
||||
return (lua_objlen(L, -1) > 0); /* check whether read something */
|
||||
}
|
||||
|
@ -347,7 +347,7 @@ static int read_line (lua_State *L, int f) {
|
|||
signed char c = EOF;
|
||||
int i = 0;
|
||||
do{
|
||||
c = (signed char)fs_getc(f);
|
||||
c = (signed char)vfs_getc(f);
|
||||
if(c==EOF){
|
||||
break;
|
||||
}
|
||||
|
@ -377,7 +377,7 @@ static int read_chars (lua_State *L, int f, size_t n) {
|
|||
do {
|
||||
char *p = luaL_prepbuffer(&b);
|
||||
if (rlen > n) rlen = n; /* cannot read more than asked */
|
||||
nr = fs_read(f, p, rlen);
|
||||
nr = vfs_read(f, p, rlen);
|
||||
luaL_addsize(&b, nr);
|
||||
n -= nr; /* still have to read `n' chars */
|
||||
} while (n > 0 && nr == rlen); /* until end of count or eof */
|
||||
|
@ -390,7 +390,7 @@ static int g_read (lua_State *L, int f, int first) {
|
|||
int nargs = lua_gettop(L) - 1;
|
||||
int success;
|
||||
int n;
|
||||
fs_clearerr(f);
|
||||
//vfs_clearerr(f);
|
||||
if (nargs == 0) { /* no arguments? */
|
||||
success = read_line(L, f);
|
||||
n = first+1; /* to return 1 result */
|
||||
|
@ -425,7 +425,7 @@ static int g_read (lua_State *L, int f, int first) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (fs_error(f))
|
||||
if (vfs_ferrno(f))
|
||||
return pushresult(L, 0, NULL);
|
||||
if (!success) {
|
||||
lua_pop(L, 1); /* remove last result */
|
||||
|
@ -453,8 +453,8 @@ static int io_readline (lua_State *L) {
|
|||
return 0;
|
||||
}
|
||||
sucess = read_line(L, *pf);
|
||||
if (fs_error(*pf))
|
||||
return luaL_error(L, "err(%d)", fs_error(*pf));
|
||||
if (vfs_ferrno(*pf))
|
||||
return luaL_error(L, "err(%d)", vfs_ferrno(*pf));
|
||||
if (sucess) return 1;
|
||||
else { /* EOF */
|
||||
if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */
|
||||
|
@ -477,14 +477,14 @@ static int g_write (lua_State *L, int f, int arg) {
|
|||
if (lua_type(L, arg) == LUA_TNUMBER) {
|
||||
/* optimization: could be done exactly as for strings */
|
||||
status = status &&
|
||||
fs_printf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
|
||||
vfs_printf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
size_t l;
|
||||
const char *s = luaL_checklstring(L, arg, &l);
|
||||
status = status && (fs_write(f, s, l) == l);
|
||||
status = status && (vfs_write(f, s, l) == l);
|
||||
}
|
||||
}
|
||||
return pushresult(L, status, NULL);
|
||||
|
@ -502,16 +502,16 @@ static int f_write (lua_State *L) {
|
|||
|
||||
|
||||
static int f_seek (lua_State *L) {
|
||||
static const int mode[] = {FS_SEEK_SET, FS_SEEK_CUR, FS_SEEK_END};
|
||||
static const int mode[] = {VFS_SEEK_SET, VFS_SEEK_CUR, VFS_SEEK_END};
|
||||
static const char *const modenames[] = {"set", "cur", "end", NULL};
|
||||
int f = tofile(L);
|
||||
int op = luaL_checkoption(L, 2, "cur", modenames);
|
||||
long offset = luaL_optlong(L, 3, 0);
|
||||
op = fs_seek(f, offset, mode[op]);
|
||||
op = vfs_lseek(f, offset, mode[op]);
|
||||
if (op)
|
||||
return pushresult(L, 0, NULL); /* error */
|
||||
else {
|
||||
lua_pushinteger(L, fs_tell(f));
|
||||
lua_pushinteger(L, vfs_tell(f));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -530,12 +530,12 @@ static int f_setvbuf (lua_State *L) {
|
|||
|
||||
|
||||
static int io_flush (lua_State *L) {
|
||||
return pushresult(L, fs_flush(getiofile(L, IO_OUTPUT)) == 0, NULL);
|
||||
return pushresult(L, vfs_flush(getiofile(L, IO_OUTPUT)) == 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
static int f_flush (lua_State *L) {
|
||||
return pushresult(L, fs_flush(tofile(L)) == 0, NULL);
|
||||
return pushresult(L, vfs_flush(tofile(L)) == 0, NULL);
|
||||
}
|
||||
|
||||
#undef MIN_OPT_LEVEL
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
#include <fcntl.h>
|
||||
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
#include "flash_fs.h"
|
||||
#include "c_stdlib.h"
|
||||
#include "vfs.h"
|
||||
#include "c_stdlib.h" // for c_getenv
|
||||
#endif
|
||||
|
||||
#include "lauxlib.h"
|
||||
|
@ -341,9 +341,9 @@ static int readable (const char *filename) {
|
|||
}
|
||||
#else
|
||||
static int readable (const char *filename) {
|
||||
int f = fs_open(filename, FS_RDONLY); /* try to open file */
|
||||
if (f < FS_OPEN_OK) return 0; /* open failed */
|
||||
fs_close(f);
|
||||
int f = vfs_open(filename, "r"); /* try to open file */
|
||||
if (!f) return 0; /* open failed */
|
||||
vfs_close(f);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -759,7 +759,6 @@ void luaV_execute (lua_State *L, int nexeccalls) {
|
|||
fixedstack(L);
|
||||
if (n == 0) {
|
||||
n = cast_int(L->top - ra) - 1;
|
||||
L->top = L->ci->top;
|
||||
}
|
||||
if (c == 0) c = cast_int(*pc++);
|
||||
runtime_check(L, ttistable(ra));
|
||||
|
@ -772,6 +771,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
|
|||
setobj2t(L, luaH_setnum(L, h, last--), val);
|
||||
luaC_barriert(L, h, val);
|
||||
}
|
||||
L->top = L->ci->top;
|
||||
unfixedstack(L);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
menu "Platform hardware config"
|
||||
menu "Platform config"
|
||||
|
||||
choice FLASH_SIZE
|
||||
bool "Platform SPI flash size"
|
||||
|
@ -105,7 +105,7 @@ config NODE_DEBUG
|
|||
Enable debugging output via NODE_DBG(). This is VERY chatty.
|
||||
For development/debugging use only.
|
||||
|
||||
config NODE_ERROR
|
||||
config NODE_ERR
|
||||
bool "Enable NODE_ERR() output"
|
||||
default "y"
|
||||
help
|
||||
|
@ -115,4 +115,21 @@ config NODE_ERROR
|
|||
something has gone seriously wrong and you probably want to know about
|
||||
it.
|
||||
|
||||
config FS_OBJ_NAME_LEN
|
||||
int "Make filesystem object name length"
|
||||
default 31
|
||||
help
|
||||
Maximum name of filesystem objects (files, directories).
|
||||
|
||||
# I don't think we can deal without SPIFFS at this point, so always on for now
|
||||
config BUILD_SPIFFS
|
||||
bool
|
||||
default "y"
|
||||
|
||||
config BUILD_FATFS
|
||||
bool "Support for FAT filesystems"
|
||||
default "n"
|
||||
help
|
||||
Include support for accessing FAT filesystems on SD cards.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#define _PLATFORM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "cpu_esp32.h"
|
||||
|
||||
#define PLATFORM_ALIGNMENT __attribute__((aligned(4)))
|
||||
|
|
|
@ -0,0 +1,250 @@
|
|||
|
||||
#ifndef __VFS_H__
|
||||
#define __VFS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "vfs_int.h"
|
||||
|
||||
// DEPRECATED, DON'T USE
|
||||
// Check for fd != 0 instead
|
||||
#define FS_OPEN_OK 1
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// file functions
|
||||
//
|
||||
|
||||
// vfs_close - close file descriptor and free memory
|
||||
// fd: file descriptor
|
||||
// Returns: VFS_RES_OK or negative value in case of error
|
||||
inline int32_t vfs_close( int fd ) {
|
||||
vfs_file *f = (vfs_file *)fd;
|
||||
return f ? f->fns->close( f ) : VFS_RES_ERR;
|
||||
}
|
||||
|
||||
// vfs_read - read data from file
|
||||
// fd: file descriptor
|
||||
// ptr: destination data buffer
|
||||
// len: requested length
|
||||
// Returns: Number of bytes read, or VFS_RES_ERR in case of error
|
||||
inline int32_t vfs_read( int fd, void *ptr, size_t len ) {
|
||||
vfs_file *f = (vfs_file *)fd;
|
||||
return f ? f->fns->read( f, ptr, len ) : VFS_RES_ERR;
|
||||
}
|
||||
|
||||
// vfs_write - write data to file
|
||||
// fd: file descriptor
|
||||
// ptr: source data buffer
|
||||
// len: requested length
|
||||
// Returns: Number of bytes written, or VFS_RES_ERR in case of error
|
||||
inline int32_t vfs_write( int fd, const void *ptr, size_t len ) {
|
||||
vfs_file *f = (vfs_file *)fd;
|
||||
return f ? f->fns->write( f, ptr, len ) : VFS_RES_ERR;
|
||||
}
|
||||
|
||||
int vfs_getc( int fd );
|
||||
|
||||
int vfs_ungetc( int c, int fd );
|
||||
|
||||
// vfs_lseek - move read/write pointer
|
||||
// fd: file descriptor
|
||||
// off: offset
|
||||
// whence: VFS_SEEK_SET - set pointer to off
|
||||
// VFS_SEEK_CUR - set pointer to current position + off
|
||||
// VFS_SEEK_END - set pointer to end of file + off
|
||||
// Returns: New position, or VFS_RES_ERR in case of error
|
||||
inline int32_t vfs_lseek( int fd, int32_t off, int whence ) {
|
||||
vfs_file *f = (vfs_file *)fd;
|
||||
return f ? f->fns->lseek( f, off, whence ) : VFS_RES_ERR;
|
||||
}
|
||||
|
||||
// vfs_eof - test for end-of-file
|
||||
// fd: file descriptor
|
||||
// Returns: 0 if not at end, != 0 if end of file
|
||||
inline int32_t vfs_eof( int fd ) {
|
||||
vfs_file *f = (vfs_file *)fd;
|
||||
return f ? f->fns->eof( f ) : VFS_RES_ERR;
|
||||
}
|
||||
|
||||
// vfs_tell - get read/write position
|
||||
// fd: file descriptor
|
||||
// Returns: Current position
|
||||
inline int32_t vfs_tell( int fd ) {
|
||||
vfs_file *f = (vfs_file *)fd;
|
||||
return f ? f->fns->tell( f ) : VFS_RES_ERR;
|
||||
}
|
||||
|
||||
// vfs_flush - flush write cache to file
|
||||
// fd: file descriptor
|
||||
// Returns: VFS_RES_OK, or VFS_RES_ERR in case of error
|
||||
inline int32_t vfs_flush( int fd ) {
|
||||
vfs_file *f = (vfs_file *)fd;
|
||||
return f ? f->fns->flush( f ) : VFS_RES_ERR;
|
||||
}
|
||||
|
||||
// vfs_size - get current file size
|
||||
// fd: file descriptor
|
||||
// Returns: File size
|
||||
inline uint32_t vfs_size( int fd ) {
|
||||
vfs_file *f = (vfs_file *)fd;
|
||||
return f && f->fns->size ? f->fns->size( f ) : 0;
|
||||
}
|
||||
|
||||
// vfs_ferrno - get file system specific errno
|
||||
// fd: file descriptor
|
||||
// Returns: errno
|
||||
int32_t vfs_ferrno( int fd );
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// dir functions
|
||||
//
|
||||
|
||||
// vfs_closedir - close directory descriptor and free memory
|
||||
// dd: dir descriptor
|
||||
// Returns: VFS_RES_OK, or VFS_RES_ERR in case of error
|
||||
inline int32_t vfs_closedir( vfs_dir *dd ) { return dd->fns->close( dd ); }
|
||||
|
||||
// vfs_readdir - read next directory item
|
||||
// dd: dir descriptor
|
||||
// Returns: item object, or NULL in case of error
|
||||
inline vfs_item *vfs_readdir( vfs_dir *dd ) { return dd->fns->readdir( dd ); }
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// dir item functions
|
||||
//
|
||||
|
||||
// vfs_closeitem - close directory item and free memory
|
||||
// di: item descriptor
|
||||
// Returns: nothing
|
||||
inline void vfs_closeitem( vfs_item *di ) { return di->fns->close( di ); }
|
||||
|
||||
// vfs_item_size - get item's size
|
||||
// di: item descriptor
|
||||
// Returns: Item size
|
||||
inline uint32_t vfs_item_size( vfs_item *di ) { return di->fns->size( di ); }
|
||||
|
||||
// vfs_item_time - get item's modification time
|
||||
// di: item descriptor
|
||||
// Returns: Item modification time
|
||||
inline int32_t vfs_item_time( vfs_item *di, struct vfs_time *tm ) { return di->fns->time ? di->fns->time( di, tm ) : VFS_RES_ERR; }
|
||||
|
||||
// vfs_item_name - get item's name
|
||||
// di: item descriptor
|
||||
// Returns: Item name
|
||||
inline const char *vfs_item_name( vfs_item *di ) { return di->fns->name( di ); }
|
||||
|
||||
// vfs_item_is_dir - check for directory
|
||||
// di: item descriptor
|
||||
// Returns: >0 if item is a directory, 0 if not
|
||||
inline int32_t vfs_item_is_dir( vfs_item *di ) { return di->fns->is_dir ? di->fns->is_dir( di ) : 0; }
|
||||
|
||||
// vfs_item_is_rdonly - check for read-only
|
||||
// di: item descriptor
|
||||
// Returns: >0 if item is read only, 0 if not
|
||||
inline int32_t vfs_item_is_rdonly( vfs_item *di ) { return di->fns->is_rdonly ? di->fns->is_rdonly( di ) : 0; }
|
||||
|
||||
// vfs_item_is_hidden - check for hidden attribute
|
||||
// di: item descriptor
|
||||
// Returns: >0 if item is hidden, 0 if not
|
||||
inline int32_t vfs_item_is_hidden( vfs_item *di ) { return di->fns->is_hidden ? di->fns->is_hidden( di ) : 0; }
|
||||
|
||||
// vfs_item_is_sys - check for sys attribute
|
||||
// di: item descriptor
|
||||
// Returns: >0 if item is sys, 0 if not
|
||||
inline int32_t vfs_item_is_sys( vfs_item *di ) { return di->fns->is_sys ? di->fns->is_sys( di ) : 0; }
|
||||
|
||||
// vfs_item_is_arch - check for archive attribute
|
||||
// di: item descriptor
|
||||
// Returns: >0 if item is archive, 0 if not
|
||||
inline int32_t vfs_item_is_arch( vfs_item *di ) { return di->fns->is_arch ? di->fns->is_arch( di ) : 0; }
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// volume functions
|
||||
//
|
||||
|
||||
// vfs_umount - unmount logical drive and free memory
|
||||
// vol: volume object
|
||||
// Returns: VFS_RES_OK, or VFS_RES_ERR in case of error
|
||||
inline int32_t vfs_umount( vfs_vol *vol ) { return vol->fns->umount( vol ); }
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// file system functions
|
||||
//
|
||||
|
||||
// vfs_mount - unmount logical drive
|
||||
// name: name of logical drive
|
||||
// num: drive's physical number (eg. SS/CS pin), negative values are ignored
|
||||
// Returns: Volume object, or NULL in case of error
|
||||
vfs_vol *vfs_mount( const char *name, int num );
|
||||
|
||||
// vfs_open - open file
|
||||
// name: file name
|
||||
// mode: open mode
|
||||
// Returns: File descriptor, or NULL in case of error
|
||||
int vfs_open( const char *name, const char *mode );
|
||||
|
||||
// vfs_opendir - open directory
|
||||
// name: dir name
|
||||
// Returns: Directory descriptor, or NULL in case of error
|
||||
vfs_dir *vfs_opendir( const char *name );
|
||||
|
||||
// vfs_stat - stat file or directory
|
||||
// name: file or directory name
|
||||
// Returns: Item object, or NULL in case of error
|
||||
vfs_item *vfs_stat( const char *name );
|
||||
|
||||
// vfs_remove - remove file or directory
|
||||
// name: file or directory name
|
||||
// Returns: VFS_RES_OK, or VFS_RES_ERR in case of error
|
||||
int32_t vfs_remove( const char *name );
|
||||
|
||||
// vfs_rename - rename file or directory
|
||||
// name: file or directory name
|
||||
// Returns: VFS_RES_OK, or VFS_RES_ERR in case of error
|
||||
int32_t vfs_rename( const char *oldname, const char *newname );
|
||||
|
||||
// vfs_mkdir - create directory
|
||||
// name: directory name
|
||||
// Returns: VFS_RES_OK, or VFS_RES_ERR in case of error
|
||||
int32_t vfs_mkdir( const char *name );
|
||||
|
||||
// vfs_fsinfo - get file system info
|
||||
// name: logical drive identifier
|
||||
// total: receives total amount
|
||||
// used: received used amount
|
||||
// Returns: VFS_RES_OK, or VFS_RES_ERR in case of error
|
||||
int32_t vfs_fsinfo( const char *name, uint32_t *total, uint32_t *used );
|
||||
|
||||
// vfs_format - format file system
|
||||
// Returns: 1, or 0 in case of error
|
||||
int32_t vfs_format( void );
|
||||
|
||||
// vfs_chdir - change default directory
|
||||
// path: new default directory
|
||||
// Returns: VFS_RES_OK, or VFS_RES_ERR in case of error
|
||||
int32_t vfs_chdir( const char *path );
|
||||
|
||||
// vfs_fscfg - query configuration settings of file system
|
||||
// phys_addr: pointer to store physical address information
|
||||
// phys_size: pointer to store physical size information
|
||||
// Returns: VFS_RES_OK, or VFS_RES_ERR in case of error
|
||||
int32_t vfs_fscfg( const char *name, uint32_t *phys_addr, uint32_t *phys_size);
|
||||
|
||||
// vfs_errno - get file system specific errno
|
||||
// name: logical drive identifier
|
||||
// Returns: errno
|
||||
int32_t vfs_errno( const char *name );
|
||||
|
||||
// vfs_clearerr - cleaer file system specific errno
|
||||
void vfs_clearerr( const char *name );
|
||||
|
||||
// vfs_register_rtc_cb - register callback function for RTC query
|
||||
// cb: pointer to callback function
|
||||
void vfs_register_rtc_cb( int32_t (*cb)( vfs_time *tm ) );
|
||||
|
||||
// vfs_basename - identify basename (incl. extension)
|
||||
// path: full file system path
|
||||
// Returns: pointer to basename within path string
|
||||
const char *vfs_basename( const char *path );
|
||||
|
||||
#endif
|
|
@ -0,0 +1,136 @@
|
|||
// internal definitions for vfs
|
||||
|
||||
#ifndef __VFS_INT_H__
|
||||
#define __VFS_INT_H__
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if 0
|
||||
#include "spiffs.h"
|
||||
|
||||
#include "fatfs_prefix_lib.h"
|
||||
#include "ff.h"
|
||||
#endif
|
||||
|
||||
|
||||
#define VFS_EOF -1
|
||||
|
||||
enum vfs_filesystems {
|
||||
VFS_FS_NONE = 0,
|
||||
VFS_FS_SPIFFS,
|
||||
VFS_FS_FATFS
|
||||
};
|
||||
|
||||
enum vfs_seek {
|
||||
VFS_SEEK_SET = 0,
|
||||
VFS_SEEK_CUR,
|
||||
VFS_SEEK_END
|
||||
};
|
||||
|
||||
enum vfs_result {
|
||||
VFS_RES_OK = 0,
|
||||
VFS_RES_ERR = -1
|
||||
};
|
||||
|
||||
|
||||
struct vfs_time {
|
||||
int year, mon, day;
|
||||
int hour, min, sec;
|
||||
};
|
||||
typedef struct vfs_time vfs_time;
|
||||
|
||||
// generic file descriptor
|
||||
struct vfs_file {
|
||||
int fs_type;
|
||||
const struct vfs_file_fns *fns;
|
||||
};
|
||||
typedef const struct vfs_file vfs_file;
|
||||
|
||||
// file descriptor functions
|
||||
struct vfs_file_fns {
|
||||
int32_t (*close)( const struct vfs_file *fd );
|
||||
int32_t (*read)( const struct vfs_file *fd, void *ptr, size_t len );
|
||||
int32_t (*write)( const struct vfs_file *fd, const void *ptr, size_t len );
|
||||
int32_t (*lseek)( const struct vfs_file *fd, int32_t off, int whence );
|
||||
int32_t (*eof)( const struct vfs_file *fd );
|
||||
int32_t (*tell)( const struct vfs_file *fd );
|
||||
int32_t (*flush)( const struct vfs_file *fd );
|
||||
uint32_t (*size)( const struct vfs_file *fd );
|
||||
int32_t (*ferrno)( const struct vfs_file *fd );
|
||||
};
|
||||
typedef const struct vfs_file_fns vfs_file_fns;
|
||||
|
||||
// generic dir item descriptor
|
||||
struct vfs_item {
|
||||
int fs_type;
|
||||
const struct vfs_item_fns *fns;
|
||||
};
|
||||
typedef const struct vfs_item vfs_item;
|
||||
|
||||
// directory item functions
|
||||
struct vfs_item_fns {
|
||||
void (*close)( const struct vfs_item *di );
|
||||
uint32_t (*size)( const struct vfs_item *di );
|
||||
int32_t (*time)( const struct vfs_item *di, struct vfs_time *tm );
|
||||
const char *(*name)( const struct vfs_item *di );
|
||||
int32_t (*is_dir)( const struct vfs_item *di );
|
||||
int32_t (*is_rdonly)( const struct vfs_item *di );
|
||||
int32_t (*is_hidden)( const struct vfs_item *di );
|
||||
int32_t (*is_sys)( const struct vfs_item *di );
|
||||
int32_t (*is_arch)( const struct vfs_item *di );
|
||||
};
|
||||
typedef const struct vfs_item_fns vfs_item_fns;
|
||||
|
||||
// generic dir descriptor
|
||||
struct vfs_dir {
|
||||
int fs_type;
|
||||
const struct vfs_dir_fns *fns;
|
||||
};
|
||||
typedef const struct vfs_dir vfs_dir;
|
||||
|
||||
// dir descriptor functions
|
||||
struct vfs_dir_fns {
|
||||
int32_t (*close)( const struct vfs_dir *dd );
|
||||
vfs_item *(*readdir)( const struct vfs_dir *dd );
|
||||
};
|
||||
typedef const struct vfs_dir_fns vfs_dir_fns;
|
||||
|
||||
// generic volume descriptor
|
||||
struct vfs_vol {
|
||||
int fs_type;
|
||||
const struct vfs_vol_fns *fns;
|
||||
};
|
||||
typedef const struct vfs_vol vfs_vol;
|
||||
|
||||
// volume functions
|
||||
struct vfs_vol_fns {
|
||||
int32_t (*umount)( const struct vfs_vol *vol );
|
||||
};
|
||||
typedef const struct vfs_vol_fns vfs_vol_fns;
|
||||
|
||||
struct vfs_fs_fns {
|
||||
vfs_vol *(*mount)( const char *name, int num );
|
||||
vfs_file *(*open)( const char *name, const char *mode );
|
||||
vfs_dir *(*opendir)( const char *name );
|
||||
vfs_item *(*stat)( const char *name );
|
||||
int32_t (*remove)( const char *name );
|
||||
int32_t (*rename)( const char *oldname, const char *newname );
|
||||
int32_t (*mkdir)( const char *name );
|
||||
int32_t (*fsinfo)( uint32_t *total, uint32_t *used );
|
||||
int32_t (*fscfg)( uint32_t *phys_addr, uint32_t *phys_size );
|
||||
int32_t (*format)( void );
|
||||
int32_t (*chdrive)( const char * );
|
||||
int32_t (*chdir)( const char * );
|
||||
int32_t (*ferrno)( void );
|
||||
void (*clearerr)( void );
|
||||
};
|
||||
typedef const struct vfs_fs_fns vfs_fs_fns;
|
||||
|
||||
|
||||
vfs_fs_fns *myspiffs_realm( const char *inname, char **outname, int set_current_drive );
|
||||
vfs_fs_fns *myfatfs_realm( const char *inname, char **outname, int set_current_drive );
|
||||
|
||||
int32_t vfs_get_rtc( vfs_time *tm );
|
||||
|
||||
#endif
|
|
@ -0,0 +1,248 @@
|
|||
#include "platform.h"
|
||||
#include "flash_api.h"
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// ****************************************************************************
|
||||
// Internal flash support functions
|
||||
|
||||
/* This symbol must be exported by the linker command file and contain the
|
||||
* size of all the sections packed into the irom0_flash.bin file, in order
|
||||
* for us to find the end of used flash.
|
||||
*/
|
||||
extern char _irom0_bin_min_sz[];
|
||||
|
||||
// Helper function: find the flash sector in which an address resides
|
||||
// Return the sector number, as well as the start and end address of the sector
|
||||
static uint32_t flashh_find_sector( uint32_t address, uint32_t *pstart, uint32_t *pend )
|
||||
{
|
||||
#ifdef INTERNAL_FLASH_SECTOR_SIZE
|
||||
// All the sectors in the flash have the same size, so just align the address
|
||||
uint32_t sect_id = address / INTERNAL_FLASH_SECTOR_SIZE;
|
||||
|
||||
if( pstart )
|
||||
*pstart = sect_id * INTERNAL_FLASH_SECTOR_SIZE ;
|
||||
if( pend )
|
||||
*pend = ( sect_id + 1 ) * INTERNAL_FLASH_SECTOR_SIZE - 1;
|
||||
return sect_id;
|
||||
#else // #ifdef INTERNAL_FLASH_SECTOR_SIZE
|
||||
// The flash has blocks of different size
|
||||
// Their size is decribed in the INTERNAL_FLASH_SECTOR_ARRAY macro
|
||||
const uint32_t flash_sect_size[] = INTERNAL_FLASH_SECTOR_ARRAY;
|
||||
uint32_t total = 0, i = 0;
|
||||
|
||||
while( ( total <= address ) && ( i < sizeof( flash_sect_size ) / sizeof( uint32_t ) ) )
|
||||
total += flash_sect_size[ i ++ ];
|
||||
if( pstart )
|
||||
*pstart = ( total - flash_sect_size[ i - 1 ] );
|
||||
if( pend )
|
||||
*pend = total - 1;
|
||||
return i - 1;
|
||||
#endif // #ifdef INTERNAL_FLASH_SECTOR_SIZE
|
||||
}
|
||||
|
||||
uint32_t platform_flash_get_sector_of_address( uint32_t addr )
|
||||
{
|
||||
return flashh_find_sector( addr, NULL, NULL );
|
||||
}
|
||||
|
||||
uint32_t platform_flash_get_num_sectors(void)
|
||||
{
|
||||
#ifdef INTERNAL_FLASH_SECTOR_SIZE
|
||||
return INTERNAL_FLASH_SIZE / INTERNAL_FLASH_SECTOR_SIZE;
|
||||
#else // #ifdef INTERNAL_FLASH_SECTOR_SIZE
|
||||
const uint32_t flash_sect_size[] = INTERNAL_FLASH_SECTOR_ARRAY;
|
||||
|
||||
return sizeof( flash_sect_size ) / sizeof( uint32_t );
|
||||
#endif // #ifdef INTERNAL_FLASH_SECTOR_SIZE
|
||||
}
|
||||
|
||||
uint32_t platform_flash_get_first_free_block_address( uint32_t *psect )
|
||||
{
|
||||
uint32_t flash_offs = IROM0_START_FLASH_ADDR + (uint32_t)_irom0_bin_min_sz;
|
||||
uint32_t sect =
|
||||
(flash_offs + INTERNAL_FLASH_SECTOR_SIZE-1)/INTERNAL_FLASH_SECTOR_SIZE;
|
||||
++sect; /* compensate for various headers not counted in _irom0_bin_min_sz */
|
||||
|
||||
if (psect)
|
||||
*psect = sect;
|
||||
|
||||
return sect * INTERNAL_FLASH_SECTOR_SIZE;
|
||||
}
|
||||
|
||||
uint32_t platform_flash_write( const void *from, uint32_t toaddr, uint32_t size )
|
||||
{
|
||||
#ifndef INTERNAL_FLASH_WRITE_UNIT_SIZE
|
||||
return platform_s_flash_write( from, toaddr, size );
|
||||
#else // #ifindef INTERNAL_FLASH_WRITE_UNIT_SIZE
|
||||
uint32_t temp, rest, ssize = size;
|
||||
unsigned i;
|
||||
char tmpdata[ INTERNAL_FLASH_WRITE_UNIT_SIZE ];
|
||||
const uint8_t *pfrom = ( const uint8_t* )from;
|
||||
const uint32_t blksize = INTERNAL_FLASH_WRITE_UNIT_SIZE;
|
||||
const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1;
|
||||
|
||||
// Align the start
|
||||
if( toaddr & blkmask )
|
||||
{
|
||||
rest = toaddr & blkmask;
|
||||
temp = toaddr & ~blkmask; // this is the actual aligned address
|
||||
// memcpy( tmpdata, ( const void* )temp, blksize );
|
||||
platform_s_flash_read( tmpdata, temp, blksize );
|
||||
for( i = rest; size && ( i < blksize ); i ++, size --, pfrom ++ )
|
||||
tmpdata[ i ] = *pfrom;
|
||||
platform_s_flash_write( tmpdata, temp, blksize );
|
||||
if( size == 0 )
|
||||
return ssize;
|
||||
toaddr = temp + blksize;
|
||||
}
|
||||
// The start address is now a multiple of blksize
|
||||
// Compute how many bytes we can write as multiples of blksize
|
||||
rest = size & blkmask;
|
||||
temp = size & ~blkmask;
|
||||
// Program the blocks now
|
||||
if( temp )
|
||||
{
|
||||
platform_s_flash_write( pfrom, toaddr, temp );
|
||||
toaddr += temp;
|
||||
pfrom += temp;
|
||||
}
|
||||
// And the final part of a block if needed
|
||||
if( rest )
|
||||
{
|
||||
// memcpy( tmpdata, ( const void* )toaddr, blksize );
|
||||
platform_s_flash_read( tmpdata, toaddr, blksize );
|
||||
for( i = 0; size && ( i < rest ); i ++, size --, pfrom ++ )
|
||||
tmpdata[ i ] = *pfrom;
|
||||
platform_s_flash_write( tmpdata, toaddr, blksize );
|
||||
}
|
||||
return ssize;
|
||||
#endif // #ifndef INTERNAL_FLASH_WRITE_UNIT_SIZE
|
||||
}
|
||||
|
||||
uint32_t platform_flash_read( void *to, uint32_t fromaddr, uint32_t size )
|
||||
{
|
||||
#ifndef INTERNAL_FLASH_READ_UNIT_SIZE
|
||||
return platform_s_flash_read( to, fromaddr, size );
|
||||
#else // #ifindef INTERNAL_FLASH_READ_UNIT_SIZE
|
||||
uint32_t temp, rest, ssize = size;
|
||||
unsigned i;
|
||||
char tmpdata[ INTERNAL_FLASH_READ_UNIT_SIZE ] __attribute__ ((aligned(INTERNAL_FLASH_READ_UNIT_SIZE)));
|
||||
uint8_t *pto = ( uint8_t* )to;
|
||||
const uint32_t blksize = INTERNAL_FLASH_READ_UNIT_SIZE;
|
||||
const uint32_t blkmask = INTERNAL_FLASH_READ_UNIT_SIZE - 1;
|
||||
|
||||
// Align the start
|
||||
if( fromaddr & blkmask )
|
||||
{
|
||||
rest = fromaddr & blkmask;
|
||||
temp = fromaddr & ~blkmask; // this is the actual aligned address
|
||||
platform_s_flash_read( tmpdata, temp, blksize );
|
||||
for( i = rest; size && ( i < blksize ); i ++, size --, pto ++ )
|
||||
*pto = tmpdata[ i ];
|
||||
|
||||
if( size == 0 )
|
||||
return ssize;
|
||||
fromaddr = temp + blksize;
|
||||
}
|
||||
// The start address is now a multiple of blksize
|
||||
// Compute how many bytes we can read as multiples of blksize
|
||||
rest = size & blkmask;
|
||||
temp = size & ~blkmask;
|
||||
// Program the blocks now
|
||||
if( temp )
|
||||
{
|
||||
platform_s_flash_read( pto, fromaddr, temp );
|
||||
fromaddr += temp;
|
||||
pto += temp;
|
||||
}
|
||||
// And the final part of a block if needed
|
||||
if( rest )
|
||||
{
|
||||
platform_s_flash_read( tmpdata, fromaddr, blksize );
|
||||
for( i = 0; size && ( i < rest ); i ++, size --, pto ++ )
|
||||
*pto = tmpdata[ i ];
|
||||
}
|
||||
return ssize;
|
||||
#endif // #ifndef INTERNAL_FLASH_READ_UNIT_SIZE
|
||||
}
|
||||
|
||||
/*
|
||||
* Assumptions:
|
||||
* > toaddr is INTERNAL_FLASH_WRITE_UNIT_SIZE aligned
|
||||
* > size is a multiple of INTERNAL_FLASH_WRITE_UNIT_SIZE
|
||||
*/
|
||||
uint32_t platform_s_flash_write( const void *from, uint32_t toaddr, uint32_t size )
|
||||
{
|
||||
SpiFlashOpResult r;
|
||||
const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1;
|
||||
uint32_t *apbuf = NULL;
|
||||
uint32_t fromaddr = (uint32_t)from;
|
||||
if( (fromaddr & blkmask ) || (fromaddr >= INTERNAL_FLASH_MAPPED_ADDRESS)) {
|
||||
apbuf = (uint32_t *)malloc(size);
|
||||
if(!apbuf)
|
||||
return 0;
|
||||
memcpy(apbuf, from, size);
|
||||
}
|
||||
r = flash_write(toaddr, apbuf?(uint32 *)apbuf:(uint32 *)from, size);
|
||||
if(apbuf)
|
||||
free(apbuf);
|
||||
if(SPI_FLASH_RESULT_OK == r)
|
||||
return size;
|
||||
else{
|
||||
NODE_ERR( "ERROR in flash_write: r=%d at %08X\n", ( int )r, ( unsigned )toaddr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Assumptions:
|
||||
* > fromaddr is INTERNAL_FLASH_READ_UNIT_SIZE aligned
|
||||
* > size is a multiple of INTERNAL_FLASH_READ_UNIT_SIZE
|
||||
*/
|
||||
uint32_t platform_s_flash_read( void *to, uint32_t fromaddr, uint32_t size )
|
||||
{
|
||||
if (size==0)
|
||||
return 0;
|
||||
|
||||
SpiFlashOpResult r;
|
||||
|
||||
const uint32_t blkmask = (INTERNAL_FLASH_READ_UNIT_SIZE - 1);
|
||||
if( ((uint32_t)to) & blkmask )
|
||||
{
|
||||
uint32_t size2=size-INTERNAL_FLASH_READ_UNIT_SIZE;
|
||||
uint32* to2=(uint32*)((((uint32_t)to)&(~blkmask))+INTERNAL_FLASH_READ_UNIT_SIZE);
|
||||
r = flash_read(fromaddr, to2, size2);
|
||||
if(SPI_FLASH_RESULT_OK == r)
|
||||
{
|
||||
memmove(to,to2,size2);
|
||||
char back[ INTERNAL_FLASH_READ_UNIT_SIZE ] __attribute__ ((aligned(INTERNAL_FLASH_READ_UNIT_SIZE)));
|
||||
r=flash_read(fromaddr+size2,(uint32*)back,INTERNAL_FLASH_READ_UNIT_SIZE);
|
||||
memcpy((uint8_t*)to+size2,back,INTERNAL_FLASH_READ_UNIT_SIZE);
|
||||
}
|
||||
}
|
||||
else
|
||||
r = flash_read(fromaddr, (uint32 *)to, size);
|
||||
|
||||
if(SPI_FLASH_RESULT_OK == r)
|
||||
return size;
|
||||
else{
|
||||
NODE_ERR( "ERROR in flash_read: r=%d at %08X\n", ( int )r, ( unsigned )fromaddr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int platform_flash_erase_sector( uint32_t sector_id )
|
||||
{
|
||||
return flash_erase( sector_id ) == SPI_FLASH_RESULT_OK ? PLATFORM_OK : PLATFORM_ERR;
|
||||
}
|
||||
|
||||
|
||||
uint32_t platform_flash_mapped2phys (uint32_t mapped_addr)
|
||||
{
|
||||
// FIXME: need to take actual memory maps into account!
|
||||
return mapped_addr - IROM0_START_MAPPED_ADDR + IROM0_START_FLASH_ADDR;
|
||||
}
|
|
@ -0,0 +1,469 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "vfs.h"
|
||||
#include "platform.h"
|
||||
|
||||
#define LDRV_TRAVERSAL 0
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// RTC system interface
|
||||
//
|
||||
static int32_t (*rtc_cb)( vfs_time *tm ) = NULL;
|
||||
|
||||
// called by operating system
|
||||
void vfs_register_rtc_cb( int32_t (*cb)( vfs_time *tm ) )
|
||||
{
|
||||
// allow NULL pointer to unregister callback function
|
||||
rtc_cb = cb;
|
||||
}
|
||||
|
||||
// called by file system drivers
|
||||
int32_t vfs_get_rtc( vfs_time *tm )
|
||||
{
|
||||
if (rtc_cb) {
|
||||
return rtc_cb( tm );
|
||||
}
|
||||
|
||||
return VFS_RES_ERR;
|
||||
}
|
||||
|
||||
|
||||
static int dir_level = 1;
|
||||
|
||||
static const char *normalize_path( const char *path )
|
||||
{
|
||||
#if ! LDRV_TRAVERSAL
|
||||
return path;
|
||||
#else
|
||||
const char *temp = path;
|
||||
size_t len;
|
||||
|
||||
while ((len = strlen( temp )) >= 2) {
|
||||
if (temp[0] == '.' && temp[1] == '.') {
|
||||
--dir_level;
|
||||
if (len >= 4 && dir_level > 0) {
|
||||
// prepare next step
|
||||
temp = &(temp[4]);
|
||||
} else {
|
||||
// we're at top, the remainder is expected be an absolute path
|
||||
temp = &(temp[3]);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dir_level > 0) {
|
||||
// no traversal on root level
|
||||
return path;
|
||||
} else {
|
||||
// path traverses via root
|
||||
return temp;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// file system functions
|
||||
//
|
||||
vfs_vol *vfs_mount( const char *name, int num )
|
||||
{
|
||||
vfs_fs_fns *fs_fns;
|
||||
const char *normname = normalize_path( name );
|
||||
char *outname;
|
||||
|
||||
#ifdef CONFIG_BUILD_SPIFFS
|
||||
if ((fs_fns = myspiffs_realm( normname, &outname, false ))) {
|
||||
return fs_fns->mount( outname, num );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BUILD_FATFS
|
||||
if ((fs_fns = myfatfs_realm( normname, &outname, false ))) {
|
||||
vfs_vol *r = fs_fns->mount( outname, num );
|
||||
free( outname );
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int vfs_open( const char *name, const char *mode )
|
||||
{
|
||||
vfs_fs_fns *fs_fns;
|
||||
const char *normname = normalize_path( name );
|
||||
char *outname;
|
||||
|
||||
#ifdef CONFIG_BUILD_SPIFFS
|
||||
if ((fs_fns = myspiffs_realm( normname, &outname, false ))) {
|
||||
return (int)fs_fns->open( outname, mode );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BUILD_FATFS
|
||||
if ((fs_fns = myfatfs_realm( normname, &outname, false ))) {
|
||||
int r = (int)fs_fns->open( outname, mode );
|
||||
free( outname );
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
vfs_dir *vfs_opendir( const char *name )
|
||||
{
|
||||
vfs_fs_fns *fs_fns;
|
||||
const char *normname = normalize_path( name );
|
||||
char *outname;
|
||||
|
||||
#ifdef CONFIG_BUILD_SPIFFS
|
||||
if ((fs_fns = myspiffs_realm( normname, &outname, false ))) {
|
||||
return fs_fns->opendir( outname );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BUILD_FATFS
|
||||
if ((fs_fns = myfatfs_realm( normname, &outname, false ))) {
|
||||
vfs_dir *r = fs_fns->opendir( outname );
|
||||
free( outname );
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vfs_item *vfs_stat( const char *name )
|
||||
{
|
||||
vfs_fs_fns *fs_fns;
|
||||
const char *normname = normalize_path( name );
|
||||
char *outname;
|
||||
|
||||
#ifdef CONFIG_BUILD_SPIFFS
|
||||
if ((fs_fns = myspiffs_realm( normname, &outname, false ))) {
|
||||
return fs_fns->stat( outname );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BUILD_FATFS
|
||||
if ((fs_fns = myfatfs_realm( normname, &outname, false ))) {
|
||||
vfs_item *r = fs_fns->stat( outname );
|
||||
free( outname );
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t vfs_remove( const char *name )
|
||||
{
|
||||
vfs_fs_fns *fs_fns;
|
||||
const char *normname = normalize_path( name );
|
||||
char *outname;
|
||||
|
||||
#ifdef CONFIG_BUILD_SPIFFS
|
||||
if ((fs_fns = myspiffs_realm( normname, &outname, false ))) {
|
||||
return fs_fns->remove( outname );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BUILD_FATFS
|
||||
if ((fs_fns = myfatfs_realm( normname, &outname, false ))) {
|
||||
int32_t r = fs_fns->remove( outname );
|
||||
free( outname );
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
return VFS_RES_ERR;
|
||||
}
|
||||
|
||||
int32_t vfs_rename( const char *oldname, const char *newname )
|
||||
{
|
||||
vfs_fs_fns *fs_fns;
|
||||
const char *normoldname = normalize_path( oldname );
|
||||
const char *normnewname = normalize_path( newname );
|
||||
char *oldoutname, *newoutname;
|
||||
|
||||
#ifdef CONFIG_BUILD_SPIFFS
|
||||
if (myspiffs_realm( normoldname, &oldoutname, false )) {
|
||||
if ((fs_fns = myspiffs_realm( normnewname, &newoutname, false ))) {
|
||||
return fs_fns->rename( oldoutname, newoutname );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BUILD_FATFS
|
||||
if (myfatfs_realm( normoldname, &oldoutname, false )) {
|
||||
if ((fs_fns = myfatfs_realm( normnewname, &newoutname, false ))) {
|
||||
int32_t r = fs_fns->rename( oldoutname, newoutname );
|
||||
free( oldoutname );
|
||||
free( newoutname );
|
||||
return r;
|
||||
}
|
||||
free( oldoutname );
|
||||
}
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t vfs_mkdir( const char *name )
|
||||
{
|
||||
vfs_fs_fns *fs_fns;
|
||||
const char *normname = normalize_path( name );
|
||||
char *outname;
|
||||
|
||||
#ifdef CONFIG_BUILD_SPIFFS
|
||||
// not supported
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BUILD_FATFS
|
||||
if ((fs_fns = myfatfs_realm( normname, &outname, false ))) {
|
||||
int32_t r = fs_fns->mkdir( outname );
|
||||
free( outname );
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
return VFS_RES_ERR;
|
||||
}
|
||||
|
||||
int32_t vfs_fsinfo( const char *name, uint32_t *total, uint32_t *used )
|
||||
{
|
||||
vfs_fs_fns *fs_fns;
|
||||
char *outname;
|
||||
|
||||
if (!name) name = ""; // current drive
|
||||
|
||||
const char *normname = normalize_path( name );
|
||||
|
||||
#ifdef CONFIG_BUILD_SPIFFS
|
||||
if ((fs_fns = myspiffs_realm( normname, &outname, false ))) {
|
||||
return fs_fns->fsinfo( total, used );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BUILD_FATFS
|
||||
if ((fs_fns = myfatfs_realm( normname, &outname, false ))) {
|
||||
free( outname );
|
||||
return fs_fns->fsinfo( total, used );
|
||||
}
|
||||
#endif
|
||||
|
||||
return VFS_RES_ERR;
|
||||
}
|
||||
|
||||
int32_t vfs_fscfg( const char *name, uint32_t *phys_addr, uint32_t *phys_size)
|
||||
{
|
||||
vfs_fs_fns *fs_fns;
|
||||
char *outname;
|
||||
|
||||
#ifdef CONFIG_BUILD_SPIFFS
|
||||
if ((fs_fns = myspiffs_realm( "/FLASH", &outname, false ))) {
|
||||
return fs_fns->fscfg( phys_addr, phys_size );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BUILD_FATFS
|
||||
// not supported
|
||||
#endif
|
||||
|
||||
// Error
|
||||
return VFS_RES_ERR;
|
||||
}
|
||||
|
||||
int32_t vfs_format( void )
|
||||
{
|
||||
vfs_fs_fns *fs_fns;
|
||||
char *outname;
|
||||
|
||||
#ifdef CONFIG_BUILD_SPIFFS
|
||||
if ((fs_fns = myspiffs_realm( "/FLASH", &outname, false ))) {
|
||||
return fs_fns->format();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BUILD_FATFS
|
||||
// not supported
|
||||
#endif
|
||||
|
||||
// Error
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t vfs_chdir( const char *path )
|
||||
{
|
||||
vfs_fs_fns *fs_fns;
|
||||
const char *normpath = normalize_path( path );
|
||||
const char *level;
|
||||
char *outname;
|
||||
int ok = VFS_RES_ERR;
|
||||
|
||||
#if LDRV_TRAVERSAL
|
||||
// track dir level
|
||||
if (normpath[0] == '/') {
|
||||
dir_level = 0;
|
||||
level = &(normpath[1]);
|
||||
} else {
|
||||
level = normpath;
|
||||
}
|
||||
while (strlen( level ) > 0) {
|
||||
dir_level++;
|
||||
if (level = strchr( level, '/' )) {
|
||||
level++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BUILD_SPIFFS
|
||||
if ((fs_fns = myspiffs_realm( normpath, &outname, true ))) {
|
||||
// our SPIFFS integration doesn't support directories
|
||||
if (strlen( outname ) == 0) {
|
||||
ok = VFS_RES_OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BUILD_FATFS
|
||||
if ((fs_fns = myfatfs_realm( normpath, &outname, true ))) {
|
||||
if (strchr( outname, ':' )) {
|
||||
// need to set FatFS' default drive
|
||||
fs_fns->chdrive( outname );
|
||||
// and force chdir to root in case path points only to root
|
||||
fs_fns->chdir( "/" );
|
||||
}
|
||||
if (fs_fns->chdir( outname ) == VFS_RES_OK) {
|
||||
ok = VFS_RES_OK;
|
||||
}
|
||||
free( outname );
|
||||
}
|
||||
#endif
|
||||
|
||||
return ok == VFS_RES_OK ? VFS_RES_OK : VFS_RES_ERR;
|
||||
}
|
||||
|
||||
int32_t vfs_errno( const char *name )
|
||||
{
|
||||
vfs_fs_fns *fs_fns;
|
||||
const char *normname = normalize_path( name );
|
||||
char *outname;
|
||||
|
||||
if (!name) name = ""; // current drive
|
||||
|
||||
#ifdef CONFIG_BUILD_SPIFFS
|
||||
if ((fs_fns = myspiffs_realm( normname, &outname, false ))) {
|
||||
return fs_fns->ferrno( );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BUILD_FATFS
|
||||
if ((fs_fns = myfatfs_realm( normname, &outname, false ))) {
|
||||
int32_t r = fs_fns->ferrno( );
|
||||
free( outname );
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
return VFS_RES_ERR;
|
||||
}
|
||||
|
||||
int32_t vfs_ferrno( int fd )
|
||||
{
|
||||
vfs_file *f = (vfs_file *)fd;
|
||||
|
||||
if (f) {
|
||||
return f->fns->ferrno ? f->fns->ferrno( f ) : 0;
|
||||
} else {
|
||||
vfs_fs_fns *fs_fns;
|
||||
const char *name = ""; // current drive
|
||||
char *outname;
|
||||
|
||||
#ifdef CONFIG_BUILD_SPIFFS
|
||||
if ((fs_fns = myspiffs_realm( name, &outname, false ))) {
|
||||
return fs_fns->ferrno( );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BUILD_FATFS
|
||||
if ((fs_fns = myfatfs_realm( name, &outname, false ))) {
|
||||
int32_t r = fs_fns->ferrno( );
|
||||
free( outname );
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void vfs_clearerr( const char *name )
|
||||
{
|
||||
vfs_fs_fns *fs_fns;
|
||||
char *outname;
|
||||
|
||||
if (!name) name = ""; // current drive
|
||||
|
||||
const char *normname = normalize_path( name );
|
||||
|
||||
#ifdef CONFIG_BUILD_SPIFFS
|
||||
if ((fs_fns = myspiffs_realm( normname, &outname, false ))) {
|
||||
fs_fns->clearerr( );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BUILD_FATFS
|
||||
if ((fs_fns = myfatfs_realm( normname, &outname, false ))) {
|
||||
fs_fns->clearerr( );
|
||||
free( outname );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *vfs_basename( const char *path )
|
||||
{
|
||||
const char *basename;
|
||||
|
||||
// deduce basename (incl. extension) for length check
|
||||
if ((basename = strrchr( path, '/' ))) {
|
||||
basename++;
|
||||
} else if ((basename = strrchr( path, ':' ))) {
|
||||
basename++;
|
||||
} else {
|
||||
basename = path;
|
||||
}
|
||||
|
||||
return basename;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// supplementary functions
|
||||
//
|
||||
int vfs_getc( int fd )
|
||||
{
|
||||
unsigned char c = 0xFF;
|
||||
int32_t res;
|
||||
|
||||
if(!vfs_eof( fd )) {
|
||||
if (1 != vfs_read( fd, &c, 1 )) {
|
||||
NODE_DBG("getc errno %i\n", vfs_ferrno( fd ));
|
||||
return VFS_EOF;
|
||||
} else {
|
||||
return (int)c;
|
||||
}
|
||||
}
|
||||
return VFS_EOF;
|
||||
}
|
||||
|
||||
int vfs_ungetc( int c, int fd )
|
||||
{
|
||||
return vfs_lseek( fd, -1, VFS_SEEK_CUR );
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2015 Peter Andersson (pelleplutt1976<at>gmail.com)
|
||||
Copyright (c) 2013-2016 Peter Andersson (pelleplutt1976<at>gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
COMPONENT_ADD_INCLUDEDIRS:=.
|
||||
|
||||
# TODO: clean up codebase to be sign clean...
|
||||
EXTRA_CFLAGS+=-Wno-error=pointer-sign
|
||||
|
||||
include $(IDF_PATH)/make/component_common.mk
|
||||
|
|
|
@ -1 +1,15 @@
|
|||
* When mending lost pages, also see if they fit into length specified in object index header
|
||||
* When mending lost pages, also see if they fit into length specified in object index header
|
||||
|
||||
SPIFFS2 thoughts
|
||||
|
||||
* Instead of exact object id:s in the object lookup tables, use a hash of span index and object id.
|
||||
Eg. object id xor:ed with bit-reversed span index.
|
||||
This should decrease number of actual pages that needs to be visited when looking thru the obj lut.
|
||||
|
||||
* Logical number of each block. When moving stuff in a garbage collected page, the free
|
||||
page is assigned the same number as the garbage collected. Thus, object index pages do not have to
|
||||
be rewritten.
|
||||
|
||||
* Steal one page, use as a bit parity page. When starting an fs modification operation, write one bit
|
||||
as zero. When ending, write another bit as zero. On mount, if number of zeroes in page is uneven, a
|
||||
check is automatically run.
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef _NODEMCU_SPIFFS_H
|
||||
#define _NODEMCU_SPIFFS_H
|
||||
|
||||
#ifndef NODEMCU_SPIFFS_NO_INCLUDE
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
// Turn off stats
|
||||
#define SPIFFS_CACHE_STATS 0
|
||||
#define SPIFFS_GC_STATS 0
|
||||
|
||||
// Needs to align stuff
|
||||
#define SPIFFS_ALIGNED_OBJECT_INDEX_TABLES 1
|
||||
|
||||
// Enable magic so we can find the file system (but not yet)
|
||||
#define SPIFFS_USE_MAGIC 1
|
||||
#define SPIFFS_USE_MAGIC_LENGTH 1
|
||||
|
||||
// Reduce the chance of returning disk full
|
||||
#define SPIFFS_GC_MAX_RUNS 256
|
||||
|
||||
#endif
|
|
@ -1,11 +1,15 @@
|
|||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include "platform.h"
|
||||
#include "flash_api.h"
|
||||
#include "spiffs.h"
|
||||
|
||||
|
||||
spiffs fs;
|
||||
|
||||
#define LOG_PAGE_SIZE 256
|
||||
#define LOG_PAGE_SIZE 256
|
||||
#define LOG_BLOCK_SIZE (INTERNAL_FLASH_SECTOR_SIZE * 2)
|
||||
#define LOG_BLOCK_SIZE_SMALL_FS (INTERNAL_FLASH_SECTOR_SIZE)
|
||||
#define MIN_BLOCKS_FS 4
|
||||
|
||||
static u8_t spiffs_work_buf[LOG_PAGE_SIZE*2];
|
||||
static u8_t spiffs_fds[32*4];
|
||||
|
@ -45,25 +49,121 @@ The small 4KB sectors allow for greater flexibility in applications th
|
|||
|
||||
********************/
|
||||
|
||||
void myspiffs_mount() {
|
||||
spiffs_config cfg;
|
||||
static bool myspiffs_set_location(spiffs_config *cfg, int align, int offset, int block_size) {
|
||||
#ifdef SPIFFS_FIXED_LOCATION
|
||||
cfg.phys_addr = SPIFFS_FIXED_LOCATION;
|
||||
cfg->phys_addr = (SPIFFS_FIXED_LOCATION + block_size - 1) & ~(block_size-1);
|
||||
#else
|
||||
cfg.phys_addr = ( u32_t )platform_flash_get_first_free_block_address( NULL );
|
||||
cfg->phys_addr = ( u32_t )platform_flash_get_first_free_block_address( NULL ) + offset;
|
||||
cfg->phys_addr = (cfg->phys_addr + align - 1) & ~(align - 1);
|
||||
#endif
|
||||
cfg.phys_addr += 0x3FFF;
|
||||
cfg.phys_addr &= 0xFFFFC000; // align to 4 sector.
|
||||
cfg.phys_size = INTERNAL_FLASH_SIZE - ( ( u32_t )cfg.phys_addr );
|
||||
cfg.phys_erase_block = INTERNAL_FLASH_SECTOR_SIZE; // according to datasheet
|
||||
cfg.log_block_size = INTERNAL_FLASH_SECTOR_SIZE; // let us not complicate things
|
||||
cfg.log_page_size = LOG_PAGE_SIZE; // as we said
|
||||
NODE_DBG("fs.start:%x,max:%x\n",cfg.phys_addr,cfg.phys_size);
|
||||
#ifdef SPIFFS_SIZE_1M_BOUNDARY
|
||||
cfg->phys_size = ((0x100000 - (SYS_PARAM_SEC_NUM * INTERNAL_FLASH_SECTOR_SIZE) - ( ( u32_t )cfg->phys_addr )) & ~(block_size - 1)) & 0xfffff;
|
||||
#else
|
||||
cfg->phys_size = (INTERNAL_FLASH_SIZE - ( ( u32_t )cfg->phys_addr )) & ~(block_size - 1);
|
||||
#endif
|
||||
if ((int) cfg->phys_size < 0) {
|
||||
return false;
|
||||
}
|
||||
cfg->log_block_size = block_size;
|
||||
|
||||
cfg.hal_read_f = my_spiffs_read;
|
||||
cfg.hal_write_f = my_spiffs_write;
|
||||
cfg.hal_erase_f = my_spiffs_erase;
|
||||
return (cfg->phys_size / block_size) >= MIN_BLOCKS_FS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if FS was found
|
||||
* align must be a power of two
|
||||
*/
|
||||
static bool myspiffs_set_cfg(spiffs_config *cfg, int align, int offset, bool force_create) {
|
||||
cfg->phys_erase_block = INTERNAL_FLASH_SECTOR_SIZE; // according to datasheet
|
||||
cfg->log_page_size = LOG_PAGE_SIZE; // as we said
|
||||
|
||||
cfg->hal_read_f = my_spiffs_read;
|
||||
cfg->hal_write_f = my_spiffs_write;
|
||||
cfg->hal_erase_f = my_spiffs_erase;
|
||||
|
||||
if (!myspiffs_set_location(cfg, align, offset, LOG_BLOCK_SIZE)) {
|
||||
if (!myspiffs_set_location(cfg, align, offset, LOG_BLOCK_SIZE_SMALL_FS)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
NODE_DBG("fs.start:%x,max:%x\n",cfg->phys_addr,cfg->phys_size);
|
||||
|
||||
#ifdef SPIFFS_USE_MAGIC_LENGTH
|
||||
if (force_create) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int size = SPIFFS_probe_fs(cfg);
|
||||
|
||||
if (size > 0 && size < cfg->phys_size) {
|
||||
NODE_DBG("Overriding size:%x\n",size);
|
||||
cfg->phys_size = size;
|
||||
}
|
||||
if (size > 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool myspiffs_find_cfg(spiffs_config *cfg, bool force_create) {
|
||||
int i;
|
||||
|
||||
if (!force_create) {
|
||||
#ifdef SPIFFS_FIXED_LOCATION
|
||||
if (myspiffs_set_cfg(cfg, 0, 0, false)) {
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
if (INTERNAL_FLASH_SIZE >= 700000) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (myspiffs_set_cfg(cfg, 0x10000, 0x10000 * i, false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (myspiffs_set_cfg(cfg, LOG_BLOCK_SIZE, LOG_BLOCK_SIZE * i, false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// No existing file system -- set up for a format
|
||||
if (INTERNAL_FLASH_SIZE >= 700000) {
|
||||
myspiffs_set_cfg(cfg, 0x10000, 0x10000, true);
|
||||
#ifndef SPIFFS_MAX_FILESYSTEM_SIZE
|
||||
if (cfg->phys_size < 400000) {
|
||||
// Don't waste so much in alignment
|
||||
myspiffs_set_cfg(cfg, LOG_BLOCK_SIZE, LOG_BLOCK_SIZE * 4, true);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
myspiffs_set_cfg(cfg, LOG_BLOCK_SIZE, 0, true);
|
||||
}
|
||||
|
||||
#ifdef SPIFFS_MAX_FILESYSTEM_SIZE
|
||||
if (cfg->phys_size > SPIFFS_MAX_FILESYSTEM_SIZE) {
|
||||
cfg->phys_size = (SPIFFS_MAX_FILESYSTEM_SIZE) & ~(cfg->log_block_size - 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool myspiffs_mount_internal(bool force_mount) {
|
||||
spiffs_config cfg;
|
||||
if (!myspiffs_find_cfg(&cfg, force_mount) && !force_mount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fs.err_code = 0;
|
||||
|
||||
int res = SPIFFS_mount(&fs,
|
||||
&cfg,
|
||||
spiffs_work_buf,
|
||||
|
@ -77,8 +177,12 @@ void myspiffs_mount() {
|
|||
#endif
|
||||
// myspiffs_check_callback);
|
||||
0);
|
||||
NODE_DBG("mount res: %i\n", res);
|
||||
(void)res;
|
||||
NODE_DBG("mount res: %d, %d\n", res, fs.err_code);
|
||||
return res == SPIFFS_OK;
|
||||
}
|
||||
|
||||
bool myspiffs_mount() {
|
||||
return myspiffs_mount_internal(false);
|
||||
}
|
||||
|
||||
void myspiffs_unmount() {
|
||||
|
@ -90,105 +194,18 @@ void myspiffs_unmount() {
|
|||
int myspiffs_format( void )
|
||||
{
|
||||
SPIFFS_unmount(&fs);
|
||||
u32_t sect_first, sect_last;
|
||||
#ifdef SPIFFS_FIXED_LOCATION
|
||||
sect_first = SPIFFS_FIXED_LOCATION;
|
||||
#else
|
||||
sect_first = ( u32_t )platform_flash_get_first_free_block_address( NULL );
|
||||
#endif
|
||||
sect_first += 0x3FFF;
|
||||
sect_first &= 0xFFFFC000; // align to 4 sector.
|
||||
sect_first = platform_flash_get_sector_of_address(sect_first);
|
||||
sect_last = INTERNAL_FLASH_SIZE - SYS_PARAM_SEC_NUM;
|
||||
sect_last = platform_flash_get_sector_of_address(sect_last);
|
||||
NODE_DBG("sect_first: %x, sect_last: %x\n", sect_first, sect_last);
|
||||
while( sect_first <= sect_last )
|
||||
if( platform_flash_erase_sector( sect_first ++ ) == PLATFORM_ERR )
|
||||
return 0;
|
||||
myspiffs_mount();
|
||||
return 1;
|
||||
}
|
||||
myspiffs_mount_internal(true);
|
||||
SPIFFS_unmount(&fs);
|
||||
|
||||
int myspiffs_check( void )
|
||||
{
|
||||
// ets_wdt_disable();
|
||||
// int res = (int)SPIFFS_check(&fs);
|
||||
// ets_wdt_enable();
|
||||
// return res;
|
||||
return 0;
|
||||
}
|
||||
NODE_DBG("Formatting: size 0x%x, addr 0x%x\n", fs.cfg.phys_size, fs.cfg.phys_addr);
|
||||
|
||||
int myspiffs_open(const char *name, int flags){
|
||||
return (int)SPIFFS_open(&fs, (char *)name, (spiffs_flags)flags, 0);
|
||||
}
|
||||
|
||||
int myspiffs_close( int fd ){
|
||||
SPIFFS_close(&fs, (spiffs_file)fd);
|
||||
return 0;
|
||||
}
|
||||
size_t myspiffs_write( int fd, const void* ptr, size_t len ){
|
||||
#if 0
|
||||
if(fd==c_stdout || fd==c_stderr){
|
||||
uart0_tx_buffer((u8_t*)ptr, len);
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
int res = SPIFFS_write(&fs, (spiffs_file)fd, (void *)ptr, len);
|
||||
if (res < 0) {
|
||||
NODE_DBG("write errno %i\n", SPIFFS_errno(&fs));
|
||||
if (SPIFFS_format(&fs) < 0) {
|
||||
return 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
size_t myspiffs_read( int fd, void* ptr, size_t len){
|
||||
int res = SPIFFS_read(&fs, (spiffs_file)fd, ptr, len);
|
||||
if (res < 0) {
|
||||
NODE_DBG("read errno %i\n", SPIFFS_errno(&fs));
|
||||
return 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
int myspiffs_lseek( int fd, int off, int whence ){
|
||||
return SPIFFS_lseek(&fs, (spiffs_file)fd, off, whence);
|
||||
}
|
||||
int myspiffs_eof( int fd ){
|
||||
return SPIFFS_eof(&fs, (spiffs_file)fd);
|
||||
}
|
||||
int myspiffs_tell( int fd ){
|
||||
return SPIFFS_tell(&fs, (spiffs_file)fd);
|
||||
}
|
||||
int myspiffs_getc( int fd ){
|
||||
unsigned char c = 0xFF;
|
||||
int res;
|
||||
if(!myspiffs_eof(fd)){
|
||||
res = SPIFFS_read(&fs, (spiffs_file)fd, &c, 1);
|
||||
if (res != 1) {
|
||||
NODE_DBG("getc errno %i\n", SPIFFS_errno(&fs));
|
||||
return (int)EOF;
|
||||
} else {
|
||||
return (int)c;
|
||||
}
|
||||
}
|
||||
return (int)EOF;
|
||||
}
|
||||
int myspiffs_ungetc( int c, int fd ){
|
||||
return SPIFFS_lseek(&fs, (spiffs_file)fd, -1, SEEK_CUR);
|
||||
}
|
||||
int myspiffs_flush( int fd ){
|
||||
return SPIFFS_fflush(&fs, (spiffs_file)fd);
|
||||
}
|
||||
int myspiffs_error( int fd ){
|
||||
return SPIFFS_errno(&fs);
|
||||
}
|
||||
void myspiffs_clearerr( int fd ){
|
||||
SPIFFS_clearerr(&fs);
|
||||
}
|
||||
int myspiffs_rename( const char *old, const char *newname ){
|
||||
return SPIFFS_rename(&fs, (char *)old, (char *)newname);
|
||||
}
|
||||
size_t myspiffs_size( int fd ){
|
||||
return SPIFFS_size(&fs, (spiffs_file)fd);
|
||||
|
||||
return myspiffs_mount();
|
||||
}
|
||||
|
||||
#if 0
|
||||
void test_spiffs() {
|
||||
char buf[12];
|
||||
|
@ -206,3 +223,406 @@ void test_spiffs() {
|
|||
NODE_DBG("--> %s <--\n", buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// vfs API
|
||||
// ***************************************************************************
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "vfs_int.h"
|
||||
|
||||
#define MY_LDRV_ID "FLASH"
|
||||
|
||||
// default current drive
|
||||
static int is_current_drive = true;
|
||||
|
||||
// forward declarations
|
||||
static int32_t myspiffs_vfs_close( const struct vfs_file *fd );
|
||||
static int32_t myspiffs_vfs_read( const struct vfs_file *fd, void *ptr, size_t len );
|
||||
static int32_t myspiffs_vfs_write( const struct vfs_file *fd, const void *ptr, size_t len );
|
||||
static int32_t myspiffs_vfs_lseek( const struct vfs_file *fd, int32_t off, int whence );
|
||||
static int32_t myspiffs_vfs_eof( const struct vfs_file *fd );
|
||||
static int32_t myspiffs_vfs_tell( const struct vfs_file *fd );
|
||||
static int32_t myspiffs_vfs_flush( const struct vfs_file *fd );
|
||||
static int32_t myspiffs_vfs_ferrno( const struct vfs_file *fd );
|
||||
|
||||
static int32_t myspiffs_vfs_closedir( const struct vfs_dir *dd );
|
||||
static vfs_item *myspiffs_vfs_readdir( const struct vfs_dir *dd );
|
||||
|
||||
static void myspiffs_vfs_iclose( const struct vfs_item *di );
|
||||
static uint32_t myspiffs_vfs_isize( const struct vfs_item *di );
|
||||
//static const struct tm *myspiffs_vfs_time( const struct vfs_item *di );
|
||||
static const char *myspiffs_vfs_name( const struct vfs_item *di );
|
||||
|
||||
static vfs_vol *myspiffs_vfs_mount( const char *name, int num );
|
||||
static vfs_file *myspiffs_vfs_open( const char *name, const char *mode );
|
||||
static vfs_dir *myspiffs_vfs_opendir( const char *name );
|
||||
static vfs_item *myspiffs_vfs_stat( const char *name );
|
||||
static int32_t myspiffs_vfs_remove( const char *name );
|
||||
static int32_t myspiffs_vfs_rename( const char *oldname, const char *newname );
|
||||
static int32_t myspiffs_vfs_fsinfo( uint32_t *total, uint32_t *used );
|
||||
static int32_t myspiffs_vfs_fscfg( uint32_t *phys_addr, uint32_t *phys_size );
|
||||
static int32_t myspiffs_vfs_format( void );
|
||||
static int32_t myspiffs_vfs_errno( void );
|
||||
static void myspiffs_vfs_clearerr( void );
|
||||
|
||||
static int32_t myspiffs_vfs_umount( const struct vfs_vol *vol );
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// function tables
|
||||
//
|
||||
static vfs_fs_fns myspiffs_fs_fns = {
|
||||
.mount = myspiffs_vfs_mount,
|
||||
.open = myspiffs_vfs_open,
|
||||
.opendir = myspiffs_vfs_opendir,
|
||||
.stat = myspiffs_vfs_stat,
|
||||
.remove = myspiffs_vfs_remove,
|
||||
.rename = myspiffs_vfs_rename,
|
||||
.mkdir = NULL,
|
||||
.fsinfo = myspiffs_vfs_fsinfo,
|
||||
.fscfg = myspiffs_vfs_fscfg,
|
||||
.format = myspiffs_vfs_format,
|
||||
.chdrive = NULL,
|
||||
.chdir = NULL,
|
||||
.ferrno = myspiffs_vfs_errno,
|
||||
.clearerr = myspiffs_vfs_clearerr
|
||||
};
|
||||
|
||||
static vfs_file_fns myspiffs_file_fns = {
|
||||
.close = myspiffs_vfs_close,
|
||||
.read = myspiffs_vfs_read,
|
||||
.write = myspiffs_vfs_write,
|
||||
.lseek = myspiffs_vfs_lseek,
|
||||
.eof = myspiffs_vfs_eof,
|
||||
.tell = myspiffs_vfs_tell,
|
||||
.flush = myspiffs_vfs_flush,
|
||||
.size = NULL,
|
||||
.ferrno = myspiffs_vfs_ferrno
|
||||
};
|
||||
|
||||
static vfs_item_fns myspiffs_item_fns = {
|
||||
.close = myspiffs_vfs_iclose,
|
||||
.size = myspiffs_vfs_isize,
|
||||
.time = NULL,
|
||||
.name = myspiffs_vfs_name,
|
||||
.is_dir = NULL,
|
||||
.is_rdonly = NULL,
|
||||
.is_hidden = NULL,
|
||||
.is_sys = NULL,
|
||||
.is_arch = NULL
|
||||
};
|
||||
|
||||
static vfs_dir_fns myspiffs_dd_fns = {
|
||||
.close = myspiffs_vfs_closedir,
|
||||
.readdir = myspiffs_vfs_readdir
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// specific struct extensions
|
||||
//
|
||||
struct myvfs_file {
|
||||
struct vfs_file vfs_file;
|
||||
spiffs_file fh;
|
||||
};
|
||||
|
||||
struct myvfs_dir {
|
||||
struct vfs_dir vfs_dir;
|
||||
spiffs_DIR d;
|
||||
};
|
||||
|
||||
struct myvfs_stat {
|
||||
struct vfs_item vfs_item;
|
||||
spiffs_stat s;
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// stat functions
|
||||
//
|
||||
#define GET_STAT_S(descr) \
|
||||
const struct myvfs_stat *mystat = (const struct myvfs_stat *)descr; \
|
||||
spiffs_stat *s = (spiffs_stat *)&(mystat->s);
|
||||
|
||||
static void myspiffs_vfs_iclose( const struct vfs_item *di ) {
|
||||
// free descriptor memory
|
||||
free( (void *)di );
|
||||
}
|
||||
|
||||
static uint32_t myspiffs_vfs_isize( const struct vfs_item *di ) {
|
||||
GET_STAT_S(di);
|
||||
|
||||
return s->size;
|
||||
}
|
||||
|
||||
static const char *myspiffs_vfs_name( const struct vfs_item *di ) {
|
||||
GET_STAT_S(di);
|
||||
|
||||
return s->name;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// volume functions
|
||||
//
|
||||
static int32_t myspiffs_vfs_umount( const struct vfs_vol *vol ) {
|
||||
// not implemented
|
||||
|
||||
return VFS_RES_ERR;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// dir functions
|
||||
//
|
||||
#define GET_DIR_D(descr) \
|
||||
const struct myvfs_dir *mydd = (const struct myvfs_dir *)descr; \
|
||||
spiffs_DIR *d = (spiffs_DIR *)&(mydd->d);
|
||||
|
||||
static int32_t myspiffs_vfs_closedir( const struct vfs_dir *dd ) {
|
||||
GET_DIR_D(dd);
|
||||
|
||||
int32_t res = SPIFFS_closedir( d );
|
||||
|
||||
// free descriptor memory
|
||||
free( (void *)dd );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static vfs_item *myspiffs_vfs_readdir( const struct vfs_dir *dd ) {
|
||||
GET_DIR_D(dd);
|
||||
struct myvfs_stat *stat;
|
||||
struct spiffs_dirent dirent;
|
||||
|
||||
if ((stat = malloc( sizeof( struct myvfs_stat ) ))) {
|
||||
if (SPIFFS_readdir( d, &dirent )) {
|
||||
stat->vfs_item.fs_type = VFS_FS_FATFS;
|
||||
stat->vfs_item.fns = &myspiffs_item_fns;
|
||||
// copy entries to vfs' directory item
|
||||
stat->s.size = dirent.size;
|
||||
strncpy( stat->s.name, dirent.name, SPIFFS_OBJ_NAME_LEN );
|
||||
return (vfs_item *)stat;
|
||||
} else {
|
||||
free( stat );
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// file functions
|
||||
//
|
||||
#define GET_FILE_FH(descr) \
|
||||
const struct myvfs_file *myfd = (const struct myvfs_file *)descr; \
|
||||
spiffs_file fh = myfd->fh;
|
||||
|
||||
static int32_t myspiffs_vfs_close( const struct vfs_file *fd ) {
|
||||
GET_FILE_FH(fd);
|
||||
|
||||
int32_t res = SPIFFS_close( &fs, fh );
|
||||
|
||||
// free descriptor memory
|
||||
free( (void *)fd );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int32_t myspiffs_vfs_read( const struct vfs_file *fd, void *ptr, size_t len ) {
|
||||
GET_FILE_FH(fd);
|
||||
|
||||
return SPIFFS_read( &fs, fh, ptr, len );
|
||||
}
|
||||
|
||||
static int32_t myspiffs_vfs_write( const struct vfs_file *fd, const void *ptr, size_t len ) {
|
||||
GET_FILE_FH(fd);
|
||||
|
||||
return SPIFFS_write( &fs, fh, (void *)ptr, len );
|
||||
}
|
||||
|
||||
static int32_t myspiffs_vfs_lseek( const struct vfs_file *fd, int32_t off, int whence ) {
|
||||
GET_FILE_FH(fd);
|
||||
int spiffs_whence;
|
||||
|
||||
switch (whence) {
|
||||
default:
|
||||
case VFS_SEEK_SET:
|
||||
spiffs_whence = SPIFFS_SEEK_SET;
|
||||
break;
|
||||
case VFS_SEEK_CUR:
|
||||
spiffs_whence = SPIFFS_SEEK_CUR;
|
||||
break;
|
||||
case VFS_SEEK_END:
|
||||
spiffs_whence = SPIFFS_SEEK_END;
|
||||
break;
|
||||
}
|
||||
|
||||
return SPIFFS_lseek( &fs, fh, off, spiffs_whence );
|
||||
}
|
||||
|
||||
static int32_t myspiffs_vfs_eof( const struct vfs_file *fd ) {
|
||||
GET_FILE_FH(fd);
|
||||
|
||||
return SPIFFS_eof( &fs, fh );
|
||||
}
|
||||
|
||||
static int32_t myspiffs_vfs_tell( const struct vfs_file *fd ) {
|
||||
GET_FILE_FH(fd);
|
||||
|
||||
return SPIFFS_tell( &fs, fh );
|
||||
}
|
||||
|
||||
static int32_t myspiffs_vfs_flush( const struct vfs_file *fd ) {
|
||||
GET_FILE_FH(fd);
|
||||
|
||||
return SPIFFS_fflush( &fs, fh ) >= 0 ? VFS_RES_OK : VFS_RES_ERR;
|
||||
}
|
||||
|
||||
static int32_t myspiffs_vfs_ferrno( const struct vfs_file *fd ) {
|
||||
return SPIFFS_errno( &fs );
|
||||
}
|
||||
|
||||
|
||||
static int fs_mode2flag(const char *mode){
|
||||
if(strlen(mode)==1){
|
||||
if(strcmp(mode,"w")==0)
|
||||
return SPIFFS_WRONLY|SPIFFS_CREAT|SPIFFS_TRUNC;
|
||||
else if(strcmp(mode, "r")==0)
|
||||
return SPIFFS_RDONLY;
|
||||
else if(strcmp(mode, "a")==0)
|
||||
return SPIFFS_WRONLY|SPIFFS_CREAT|SPIFFS_APPEND;
|
||||
else
|
||||
return SPIFFS_RDONLY;
|
||||
} else if (strlen(mode)==2){
|
||||
if(strcmp(mode,"r+")==0)
|
||||
return SPIFFS_RDWR;
|
||||
else if(strcmp(mode, "w+")==0)
|
||||
return SPIFFS_RDWR|SPIFFS_CREAT|SPIFFS_TRUNC;
|
||||
else if(strcmp(mode, "a+")==0)
|
||||
return SPIFFS_RDWR|SPIFFS_CREAT|SPIFFS_APPEND;
|
||||
else
|
||||
return SPIFFS_RDONLY;
|
||||
} else {
|
||||
return SPIFFS_RDONLY;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// filesystem functions
|
||||
//
|
||||
static vfs_file *myspiffs_vfs_open( const char *name, const char *mode ) {
|
||||
struct myvfs_file *fd;
|
||||
int flags = fs_mode2flag( mode );
|
||||
|
||||
if ((fd = (struct myvfs_file *)malloc( sizeof( struct myvfs_file ) ))) {
|
||||
if (0 < (fd->fh = SPIFFS_open( &fs, name, flags, 0 ))) {
|
||||
fd->vfs_file.fs_type = VFS_FS_SPIFFS;
|
||||
fd->vfs_file.fns = &myspiffs_file_fns;
|
||||
return (vfs_file *)fd;
|
||||
} else {
|
||||
free( fd );
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static vfs_dir *myspiffs_vfs_opendir( const char *name ){
|
||||
struct myvfs_dir *dd;
|
||||
|
||||
if ((dd = (struct myvfs_dir *)malloc( sizeof( struct myvfs_dir ) ))) {
|
||||
if (SPIFFS_opendir( &fs, name, &(dd->d) )) {
|
||||
dd->vfs_dir.fs_type = VFS_FS_SPIFFS;
|
||||
dd->vfs_dir.fns = &myspiffs_dd_fns;
|
||||
return (vfs_dir *)dd;
|
||||
} else {
|
||||
free( dd );
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static vfs_item *myspiffs_vfs_stat( const char *name ) {
|
||||
struct myvfs_stat *s;
|
||||
|
||||
if ((s = (struct myvfs_stat *)malloc( sizeof( struct myvfs_stat ) ))) {
|
||||
if (0 <= SPIFFS_stat( &fs, name, &(s->s) )) {
|
||||
s->vfs_item.fs_type = VFS_FS_SPIFFS;
|
||||
s->vfs_item.fns = &myspiffs_item_fns;
|
||||
return (vfs_item *)s;
|
||||
} else {
|
||||
free( s );
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int32_t myspiffs_vfs_remove( const char *name ) {
|
||||
return SPIFFS_remove( &fs, name );
|
||||
}
|
||||
|
||||
static int32_t myspiffs_vfs_rename( const char *oldname, const char *newname ) {
|
||||
return SPIFFS_rename( &fs, oldname, newname );
|
||||
}
|
||||
|
||||
static int32_t myspiffs_vfs_fsinfo( uint32_t *total, uint32_t *used ) {
|
||||
return SPIFFS_info( &fs, total, used );
|
||||
}
|
||||
|
||||
static int32_t myspiffs_vfs_fscfg( uint32_t *phys_addr, uint32_t *phys_size ) {
|
||||
*phys_addr = fs.cfg.phys_addr;
|
||||
*phys_size = fs.cfg.phys_size;
|
||||
return VFS_RES_OK;
|
||||
}
|
||||
|
||||
static vfs_vol *myspiffs_vfs_mount( const char *name, int num ) {
|
||||
// volume descriptor not supported, just return true / false
|
||||
return myspiffs_mount() ? (vfs_vol *)1 : NULL;
|
||||
}
|
||||
|
||||
static int32_t myspiffs_vfs_format( void ) {
|
||||
return myspiffs_format();
|
||||
}
|
||||
|
||||
static int32_t myspiffs_vfs_errno( void ) {
|
||||
return SPIFFS_errno( &fs );
|
||||
}
|
||||
|
||||
static void myspiffs_vfs_clearerr( void ) {
|
||||
SPIFFS_clearerr( &fs );
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// VFS interface functions
|
||||
//
|
||||
vfs_fs_fns *myspiffs_realm( const char *inname, char **outname, int set_current_drive ) {
|
||||
if (inname[0] == '/') {
|
||||
size_t idstr_len = strlen( MY_LDRV_ID );
|
||||
// logical drive is specified, check if it's our id
|
||||
if (0 == strncmp( &(inname[1]), MY_LDRV_ID, idstr_len )) {
|
||||
*outname = (char *)&(inname[1 + idstr_len]);
|
||||
if (*outname[0] == '/') {
|
||||
// skip leading /
|
||||
(*outname)++;
|
||||
}
|
||||
|
||||
if (set_current_drive) is_current_drive = true;
|
||||
return &myspiffs_fs_fns;
|
||||
}
|
||||
} else {
|
||||
// no logical drive in patchspec, are we current drive?
|
||||
if (is_current_drive) {
|
||||
*outname = (char *)inname;
|
||||
return &myspiffs_fs_fns;
|
||||
}
|
||||
}
|
||||
|
||||
if (set_current_drive) is_current_drive = false;
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
* Author: petera
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef SPIFFS_H_
|
||||
#define SPIFFS_H_
|
||||
#if defined(__cplusplus)
|
||||
|
@ -49,6 +47,15 @@ extern "C" {
|
|||
|
||||
#define SPIFFS_ERR_NO_DELETED_BLOCKS -10029
|
||||
|
||||
#define SPIFFS_ERR_FILE_EXISTS -10030
|
||||
|
||||
#define SPIFFS_ERR_NOT_A_FILE -10031
|
||||
#define SPIFFS_ERR_RO_NOT_IMPL -10032
|
||||
#define SPIFFS_ERR_RO_ABORTED_OPERATION -10033
|
||||
#define SPIFFS_ERR_PROBE_TOO_FEW_BLOCKS -10034
|
||||
#define SPIFFS_ERR_PROBE_NOT_A_FS -10035
|
||||
#define SPIFFS_ERR_NAME_TOO_LONG -10036
|
||||
|
||||
#define SPIFFS_ERR_INTERNAL -10050
|
||||
|
||||
#define SPIFFS_ERR_TEST -10100
|
||||
|
@ -63,12 +70,26 @@ typedef u16_t spiffs_mode;
|
|||
// object type
|
||||
typedef u8_t spiffs_obj_type;
|
||||
|
||||
struct spiffs_t;
|
||||
|
||||
#if SPIFFS_HAL_CALLBACK_EXTRA
|
||||
|
||||
/* spi read call function type */
|
||||
typedef s32_t (*spiffs_read)(struct spiffs_t *fs, u32_t addr, u32_t size, u8_t *dst);
|
||||
/* spi write call function type */
|
||||
typedef s32_t (*spiffs_write)(struct spiffs_t *fs, u32_t addr, u32_t size, u8_t *src);
|
||||
/* spi erase call function type */
|
||||
typedef s32_t (*spiffs_erase)(struct spiffs_t *fs, u32_t addr, u32_t size);
|
||||
|
||||
#else // SPIFFS_HAL_CALLBACK_EXTRA
|
||||
|
||||
/* spi read call function type */
|
||||
typedef s32_t (*spiffs_read)(u32_t addr, u32_t size, u8_t *dst);
|
||||
/* spi write call function type */
|
||||
typedef s32_t (*spiffs_write)(u32_t addr, u32_t size, u8_t *src);
|
||||
/* spi erase call function type */
|
||||
typedef s32_t (*spiffs_erase)(u32_t addr, u32_t size);
|
||||
#endif // SPIFFS_HAL_CALLBACK_EXTRA
|
||||
|
||||
/* file system check callback report operation */
|
||||
typedef enum {
|
||||
|
@ -85,12 +106,30 @@ typedef enum {
|
|||
SPIFFS_CHECK_FIX_LOOKUP,
|
||||
SPIFFS_CHECK_DELETE_ORPHANED_INDEX,
|
||||
SPIFFS_CHECK_DELETE_PAGE,
|
||||
SPIFFS_CHECK_DELETE_BAD_FILE,
|
||||
SPIFFS_CHECK_DELETE_BAD_FILE
|
||||
} spiffs_check_report;
|
||||
|
||||
/* file system check callback function */
|
||||
#if SPIFFS_HAL_CALLBACK_EXTRA
|
||||
typedef void (*spiffs_check_callback)(struct spiffs_t *fs, spiffs_check_type type, spiffs_check_report report,
|
||||
u32_t arg1, u32_t arg2);
|
||||
#else // SPIFFS_HAL_CALLBACK_EXTRA
|
||||
typedef void (*spiffs_check_callback)(spiffs_check_type type, spiffs_check_report report,
|
||||
u32_t arg1, u32_t arg2);
|
||||
#endif // SPIFFS_HAL_CALLBACK_EXTRA
|
||||
|
||||
/* file system listener callback operation */
|
||||
typedef enum {
|
||||
/* the file has been created */
|
||||
SPIFFS_CB_CREATED = 0,
|
||||
/* the file has been updated or moved to another page */
|
||||
SPIFFS_CB_UPDATED,
|
||||
/* the file has been deleted */
|
||||
SPIFFS_CB_DELETED
|
||||
} spiffs_fileop_type;
|
||||
|
||||
/* file system listener callback function */
|
||||
typedef void (*spiffs_file_callback)(struct spiffs_t *fs, spiffs_fileop_type op, spiffs_obj_id obj_id, spiffs_page_ix pix);
|
||||
|
||||
#ifndef SPIFFS_DBG
|
||||
#define SPIFFS_DBG(...) \
|
||||
|
@ -108,18 +147,28 @@ typedef void (*spiffs_check_callback)(spiffs_check_type type, spiffs_check_repor
|
|||
|
||||
/* Any write to the filehandle is appended to end of the file */
|
||||
#define SPIFFS_APPEND (1<<0)
|
||||
#define SPIFFS_O_APPEND SPIFFS_APPEND
|
||||
/* If the opened file exists, it will be truncated to zero length before opened */
|
||||
#define SPIFFS_TRUNC (1<<1)
|
||||
#define SPIFFS_O_TRUNC SPIFFS_TRUNC
|
||||
/* If the opened file does not exist, it will be created before opened */
|
||||
#define SPIFFS_CREAT (1<<2)
|
||||
#define SPIFFS_O_CREAT SPIFFS_CREAT
|
||||
/* The opened file may only be read */
|
||||
#define SPIFFS_RDONLY (1<<3)
|
||||
/* The opened file may only be writted */
|
||||
#define SPIFFS_O_RDONLY SPIFFS_RDONLY
|
||||
/* The opened file may only be written */
|
||||
#define SPIFFS_WRONLY (1<<4)
|
||||
/* The opened file may be both read and writted */
|
||||
#define SPIFFS_O_WRONLY SPIFFS_WRONLY
|
||||
/* The opened file may be both read and written */
|
||||
#define SPIFFS_RDWR (SPIFFS_RDONLY | SPIFFS_WRONLY)
|
||||
/* Any writes to the filehandle will never be cached */
|
||||
#define SPIFFS_O_RDWR SPIFFS_RDWR
|
||||
/* Any writes to the filehandle will never be cached but flushed directly */
|
||||
#define SPIFFS_DIRECT (1<<5)
|
||||
#define SPIFFS_O_DIRECT SPIFFS_DIRECT
|
||||
/* If SPIFFS_O_CREAT and SPIFFS_O_EXCL are set, SPIFFS_open() shall fail if the file exists */
|
||||
#define SPIFFS_EXCL (1<<6)
|
||||
#define SPIFFS_O_EXCL SPIFFS_EXCL
|
||||
|
||||
#define SPIFFS_SEEK_SET (0)
|
||||
#define SPIFFS_SEEK_CUR (1)
|
||||
|
@ -164,10 +213,15 @@ typedef struct {
|
|||
// logical size of a page, must be at least
|
||||
// log_block_size / 8
|
||||
u32_t log_page_size;
|
||||
|
||||
#endif
|
||||
#if SPIFFS_FILEHDL_OFFSET
|
||||
// an integer offset added to each file handle
|
||||
u16_t fh_ix_offset;
|
||||
#endif
|
||||
} spiffs_config;
|
||||
|
||||
typedef struct {
|
||||
typedef struct spiffs_t {
|
||||
// file system configuration
|
||||
spiffs_config cfg;
|
||||
// number of logical blocks
|
||||
|
@ -222,9 +276,12 @@ typedef struct {
|
|||
|
||||
// check callback function
|
||||
spiffs_check_callback check_cb_f;
|
||||
|
||||
// file callback function
|
||||
spiffs_file_callback file_cb_f;
|
||||
// mounted flag
|
||||
u8_t mounted;
|
||||
// user data
|
||||
void *user_data;
|
||||
// config magic
|
||||
u32_t config_magic;
|
||||
} spiffs;
|
||||
|
@ -234,6 +291,7 @@ typedef struct {
|
|||
spiffs_obj_id obj_id;
|
||||
u32_t size;
|
||||
spiffs_obj_type type;
|
||||
spiffs_page_ix pix;
|
||||
u8_t name[SPIFFS_OBJ_NAME_LEN];
|
||||
} spiffs_stat;
|
||||
|
||||
|
@ -253,6 +311,40 @@ typedef struct {
|
|||
|
||||
// functions
|
||||
|
||||
#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
|
||||
/**
|
||||
* Special function. This takes a spiffs config struct and returns the number
|
||||
* of blocks this file system was formatted with. This function relies on
|
||||
* that following info is set correctly in given config struct:
|
||||
*
|
||||
* phys_addr, log_page_size, and log_block_size.
|
||||
*
|
||||
* Also, hal_read_f must be set in the config struct.
|
||||
*
|
||||
* One must be sure of the correct page size and that the physical address is
|
||||
* correct in the probed file system when calling this function. It is not
|
||||
* checked if the phys_addr actually points to the start of the file system,
|
||||
* so one might get a false positive if entering a phys_addr somewhere in the
|
||||
* middle of the file system at block boundary. In addition, it is not checked
|
||||
* if the page size is actually correct. If it is not, weird file system sizes
|
||||
* will be returned.
|
||||
*
|
||||
* If this function detects a file system it returns the assumed file system
|
||||
* size, which can be used to set the phys_size.
|
||||
*
|
||||
* Otherwise, it returns an error indicating why it is not regarded as a file
|
||||
* system.
|
||||
*
|
||||
* Note: this function is not protected with SPIFFS_LOCK and SPIFFS_UNLOCK
|
||||
* macros. It returns the error code directly, instead of as read by
|
||||
* SPIFFS_errno.
|
||||
*
|
||||
* @param config essential parts of the physical and logical
|
||||
* configuration of the file system.
|
||||
*/
|
||||
s32_t SPIFFS_probe_fs(spiffs_config *config);
|
||||
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
|
||||
|
||||
/**
|
||||
* Initializes the file system dynamic parameters and mounts the filesystem.
|
||||
* If SPIFFS_USE_MAGIC is enabled the mounting may fail with SPIFFS_ERR_NOT_A_FS
|
||||
|
@ -286,19 +378,18 @@ void SPIFFS_unmount(spiffs *fs);
|
|||
* @param path the path of the new file
|
||||
* @param mode ignored, for posix compliance
|
||||
*/
|
||||
s32_t SPIFFS_creat(spiffs *fs, char *path, spiffs_mode mode);
|
||||
s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode);
|
||||
|
||||
/**
|
||||
* Opens/creates a file.
|
||||
* @param fs the file system struct
|
||||
* @param path the path of the new file
|
||||
* @param flags the flags for the open command, can be combinations of
|
||||
* SPIFFS_APPEND, SPIFFS_TRUNC, SPIFFS_CREAT, SPIFFS_RD_ONLY,
|
||||
* SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT
|
||||
* SPIFFS_O_APPEND, SPIFFS_O_TRUNC, SPIFFS_O_CREAT, SPIFFS_O_RDONLY,
|
||||
* SPIFFS_O_WRONLY, SPIFFS_O_RDWR, SPIFFS_O_DIRECT, SPIFFS_O_EXCL
|
||||
* @param mode ignored, for posix compliance
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* Opens a file by given dir entry.
|
||||
|
@ -306,7 +397,7 @@ spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode
|
|||
* a normal SPIFFS_open would need to traverse the filesystem again to find
|
||||
* the file, whilst SPIFFS_open_by_dirent already knows where the file resides.
|
||||
* @param fs the file system struct
|
||||
* @param path the dir entry to the file
|
||||
* @param e the dir entry to the file
|
||||
* @param flags the flags for the open command, can be combinations of
|
||||
* SPIFFS_APPEND, SPIFFS_TRUNC, SPIFFS_CREAT, SPIFFS_RD_ONLY,
|
||||
* SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT.
|
||||
|
@ -315,6 +406,22 @@ spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode
|
|||
*/
|
||||
spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_flags flags, spiffs_mode mode);
|
||||
|
||||
/**
|
||||
* Opens a file by given page index.
|
||||
* Optimization purposes, opens a file by directly pointing to the page
|
||||
* index in the spi flash.
|
||||
* If the page index does not point to a file header SPIFFS_ERR_NOT_A_FILE
|
||||
* is returned.
|
||||
* @param fs the file system struct
|
||||
* @param page_ix the page index
|
||||
* @param flags the flags for the open command, can be combinations of
|
||||
* SPIFFS_APPEND, SPIFFS_TRUNC, SPIFFS_CREAT, SPIFFS_RD_ONLY,
|
||||
* SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT.
|
||||
* SPIFFS_CREAT will have no effect in this case.
|
||||
* @param mode ignored, for posix compliance
|
||||
*/
|
||||
spiffs_file SPIFFS_open_by_page(spiffs *fs, spiffs_page_ix page_ix, spiffs_flags flags, spiffs_mode mode);
|
||||
|
||||
/**
|
||||
* Reads from given filehandle.
|
||||
* @param fs the file system struct
|
||||
|
@ -336,13 +443,14 @@ s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len);
|
|||
s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len);
|
||||
|
||||
/**
|
||||
* Moves the read/write file offset
|
||||
* Moves the read/write file offset. Resulting offset is returned or negative if error.
|
||||
* lseek(fs, fd, 0, SPIFFS_SEEK_CUR) will thus return current offset.
|
||||
* @param fs the file system struct
|
||||
* @param fh the filehandle
|
||||
* @param offs how much/where to move the offset
|
||||
* @param whence if SPIFFS_SEEK_SET, the file offset shall be set to offset bytes
|
||||
* if SPIFFS_SEEK_CUR, the file offset shall be set to its current location plus offset
|
||||
* if SPIFFS_SEEK_END, the file offset shall be set to the size of the file plus offset
|
||||
* if SPIFFS_SEEK_END, the file offset shall be set to the size of the file plus offse, which should be negative
|
||||
*/
|
||||
s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence);
|
||||
|
||||
|
@ -351,7 +459,7 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence);
|
|||
* @param fs the file system struct
|
||||
* @param path the path of the file to remove
|
||||
*/
|
||||
s32_t SPIFFS_remove(spiffs *fs, char *path);
|
||||
s32_t SPIFFS_remove(spiffs *fs, const char *path);
|
||||
|
||||
/**
|
||||
* Removes a file by filehandle
|
||||
|
@ -366,7 +474,7 @@ s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh);
|
|||
* @param path the path of the file to stat
|
||||
* @param s the stat struct to populate
|
||||
*/
|
||||
s32_t SPIFFS_stat(spiffs *fs, char *path, spiffs_stat *s);
|
||||
s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s);
|
||||
|
||||
/**
|
||||
* Gets file status by filehandle
|
||||
|
@ -388,7 +496,7 @@ s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh);
|
|||
* @param fs the file system struct
|
||||
* @param fh the filehandle of the file to close
|
||||
*/
|
||||
void SPIFFS_close(spiffs *fs, spiffs_file fh);
|
||||
s32_t SPIFFS_close(spiffs *fs, spiffs_file fh);
|
||||
|
||||
/**
|
||||
* Renames a file
|
||||
|
@ -396,7 +504,7 @@ void SPIFFS_close(spiffs *fs, spiffs_file fh);
|
|||
* @param old path of file to rename
|
||||
* @param newPath new path of file
|
||||
*/
|
||||
s32_t SPIFFS_rename(spiffs *fs, char *old, char *newPath);
|
||||
s32_t SPIFFS_rename(spiffs *fs, const char *old, const char *newPath);
|
||||
|
||||
/**
|
||||
* Returns last error of last file operation.
|
||||
|
@ -419,7 +527,7 @@ void SPIFFS_clearerr(spiffs *fs);
|
|||
* @param name the name of the directory
|
||||
* @param d pointer the directory stream to be populated
|
||||
*/
|
||||
spiffs_DIR *SPIFFS_opendir(spiffs *fs, char *name, spiffs_DIR *d);
|
||||
spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d);
|
||||
|
||||
/**
|
||||
* Closes a directory stream
|
||||
|
@ -441,13 +549,6 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e);
|
|||
*/
|
||||
s32_t SPIFFS_check(spiffs *fs);
|
||||
|
||||
/**
|
||||
* Searches for a block with only deleted entries. If found, it is erased.
|
||||
* @param fs the file system struct
|
||||
*/
|
||||
s32_t SPIFFS_erase_deleted_block(spiffs *fs);
|
||||
|
||||
|
||||
/**
|
||||
* Returns number of total bytes available and number of used bytes.
|
||||
* This is an estimation, and depends on if there a many files with little
|
||||
|
@ -527,6 +628,36 @@ s32_t SPIFFS_gc_quick(spiffs *fs, u16_t max_free_pages);
|
|||
*/
|
||||
s32_t SPIFFS_gc(spiffs *fs, u32_t size);
|
||||
|
||||
/**
|
||||
* Check if EOF reached.
|
||||
* @param fs the file system struct
|
||||
* @param fh the filehandle of the file to check
|
||||
*/
|
||||
s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh);
|
||||
|
||||
/**
|
||||
* Get position in file.
|
||||
* @param fs the file system struct
|
||||
* @param fh the filehandle of the file to check
|
||||
*/
|
||||
s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh);
|
||||
|
||||
/**
|
||||
* Registers a callback function that keeps track on operations on file
|
||||
* headers. Do note, that this callback is called from within internal spiffs
|
||||
* mechanisms. Any operations on the actual file system being callbacked from
|
||||
* in this callback will mess things up for sure - do not do this.
|
||||
* This can be used to track where files are and move around during garbage
|
||||
* collection, which in turn can be used to build location tables in ram.
|
||||
* Used in conjuction with SPIFFS_open_by_page this may improve performance
|
||||
* when opening a lot of files.
|
||||
* Must be invoked after mount.
|
||||
*
|
||||
* @param fs the file system struct
|
||||
* @param cb_func the callback on file operations
|
||||
*/
|
||||
s32_t SPIFFS_set_file_callback_func(spiffs *fs, spiffs_file_callback cb_func);
|
||||
|
||||
#if SPIFFS_TEST_VISUALISATION
|
||||
/**
|
||||
* Prints out a visualization of the filesystem.
|
||||
|
@ -553,30 +684,6 @@ u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages);
|
|||
|
||||
#if SPIFFS_CACHE
|
||||
#endif
|
||||
|
||||
void myspiffs_mount();
|
||||
void myspiffs_unmount();
|
||||
int myspiffs_open(const char *name, int flags);
|
||||
int myspiffs_close( int fd );
|
||||
size_t myspiffs_write( int fd, const void* ptr, size_t len );
|
||||
size_t myspiffs_read( int fd, void* ptr, size_t len);
|
||||
int myspiffs_lseek( int fd, int off, int whence );
|
||||
int myspiffs_eof( int fd );
|
||||
int myspiffs_tell( int fd );
|
||||
int myspiffs_getc( int fd );
|
||||
int myspiffs_ungetc( int c, int fd );
|
||||
int myspiffs_flush( int fd );
|
||||
int myspiffs_error( int fd );
|
||||
void myspiffs_clearerr( int fd );
|
||||
int myspiffs_check( void );
|
||||
int myspiffs_rename( const char *old, const char *newname );
|
||||
size_t myspiffs_size( int fd );
|
||||
int myspiffs_format (void);
|
||||
|
||||
s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh);
|
||||
s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh);
|
||||
s32_t SPIFFS_size(spiffs *fs, spiffs_file fh);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "spiffs.h"
|
||||
#include "spiffs_nucleus.h"
|
||||
#include <string.h>
|
||||
|
||||
#if SPIFFS_CACHE
|
||||
|
||||
|
@ -39,7 +40,7 @@ static s32_t spiffs_cache_page_free(spiffs *fs, int ix, u8_t write_back) {
|
|||
(cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 &&
|
||||
(cp->flags & SPIFFS_CACHE_FLAG_DIRTY)) {
|
||||
u8_t *mem = spiffs_get_cache_page(fs, cache, ix);
|
||||
res = fs->cfg.hal_write_f(SPIFFS_PAGE_TO_PADDR(fs, cp->pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), mem);
|
||||
res = SPIFFS_HAL_WRITE(fs, SPIFFS_PAGE_TO_PADDR(fs, cp->pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), mem);
|
||||
}
|
||||
|
||||
cp->flags = 0;
|
||||
|
@ -137,10 +138,7 @@ s32_t spiffs_phys_rd(
|
|||
} else {
|
||||
if ((op & SPIFFS_OP_TYPE_MASK) == SPIFFS_OP_T_OBJ_LU2) {
|
||||
// for second layer lookup functions, we do not cache in order to prevent shredding
|
||||
return fs->cfg.hal_read_f(
|
||||
addr ,
|
||||
len,
|
||||
dst);
|
||||
return SPIFFS_HAL_READ(fs, addr, len, dst);
|
||||
}
|
||||
#if SPIFFS_CACHE_STATS
|
||||
fs->cache_misses++;
|
||||
|
@ -151,8 +149,7 @@ s32_t spiffs_phys_rd(
|
|||
cp->flags = SPIFFS_CACHE_FLAG_WRTHRU;
|
||||
cp->pix = SPIFFS_PADDR_TO_PAGE(fs, addr);
|
||||
}
|
||||
|
||||
s32_t res2 = fs->cfg.hal_read_f(
|
||||
s32_t res2 = SPIFFS_HAL_READ(fs,
|
||||
addr - SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr),
|
||||
SPIFFS_CFG_LOG_PAGE_SZ(fs),
|
||||
spiffs_get_cache_page(fs, cache, cp->ix));
|
||||
|
@ -186,7 +183,7 @@ s32_t spiffs_phys_wr(
|
|||
(op & SPIFFS_OP_TYPE_MASK) != SPIFFS_OP_T_OBJ_LU) {
|
||||
// page is being deleted, wipe from cache - unless it is a lookup page
|
||||
spiffs_cache_page_free(fs, cp->ix, 0);
|
||||
return fs->cfg.hal_write_f(addr, len, src);
|
||||
return SPIFFS_HAL_WRITE(fs, addr, len, src);
|
||||
}
|
||||
|
||||
u8_t *mem = spiffs_get_cache_page(fs, cache, cp->ix);
|
||||
|
@ -197,13 +194,13 @@ s32_t spiffs_phys_wr(
|
|||
|
||||
if (cp->flags & SPIFFS_CACHE_FLAG_WRTHRU) {
|
||||
// page is being updated, no write-cache, just pass thru
|
||||
return fs->cfg.hal_write_f(addr, len, src);
|
||||
return SPIFFS_HAL_WRITE(fs, addr, len, src);
|
||||
} else {
|
||||
return SPIFFS_OK;
|
||||
}
|
||||
} else {
|
||||
// no cache page, no write cache - just write thru
|
||||
return fs->cfg.hal_write_f(addr, len, src);
|
||||
return SPIFFS_HAL_WRITE(fs, addr, len, src);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,24 @@
|
|||
* Author: petera
|
||||
*/
|
||||
|
||||
|
||||
#include "spiffs.h"
|
||||
#include "spiffs_nucleus.h"
|
||||
#include <string.h>
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
|
||||
#if SPIFFS_HAL_CALLBACK_EXTRA
|
||||
#define CHECK_CB(_fs, _type, _rep, _arg1, _arg2) \
|
||||
do { \
|
||||
if ((_fs)->check_cb_f) (_fs)->check_cb_f((_fs), (_type), (_rep), (_arg1), (_arg2)); \
|
||||
} while (0)
|
||||
#else
|
||||
#define CHECK_CB(_fs, _type, _rep, _arg1, _arg2) \
|
||||
do { \
|
||||
if ((_fs)->check_cb_f) (_fs)->check_cb_f((_type), (_rep), (_arg1), (_arg2)); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
//---------------------------------------
|
||||
// Look up consistency
|
||||
|
@ -93,6 +109,7 @@ static s32_t spiffs_rewrite_index(spiffs *fs, spiffs_obj_id obj_id, spiffs_span_
|
|||
} else {
|
||||
// calc entry in index
|
||||
entry = SPIFFS_OBJ_IX_ENTRY(fs, data_spix);
|
||||
|
||||
}
|
||||
// load index
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
|
@ -194,9 +211,9 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
|
|||
res = spiffs_page_delete(fs, new_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
res = spiffs_delete_obj_lazy(fs, p_hdr->obj_id);
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr->obj_id, 0);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr->obj_id, 0);
|
||||
} else {
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_INDEX, p_hdr->obj_id, p_hdr->span_ix);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_INDEX, p_hdr->obj_id, p_hdr->span_ix);
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
|
@ -216,7 +233,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
|
|||
SPIFFS_CHECK_DBG("LU: FIXUP: ix page with data not found elsewhere, rewriting %04x to new page %04x\n", cur_pix, new_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
*reload_lu = 1;
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
|
||||
}
|
||||
} else {
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
@ -254,7 +271,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
|
|||
SPIFFS_CHECK_RES(res);
|
||||
res = spiffs_delete_obj_lazy(fs, p_hdr->obj_id);
|
||||
*reload_lu = 1;
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr->obj_id, 0);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr->obj_id, 0);
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
|
@ -306,7 +323,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
|
|||
new_ph.obj_id = p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG;
|
||||
res = spiffs_rewrite_page(fs, cur_pix, &new_ph, &new_pix);
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: rewrite page %04x as %04x to pix %04x\n", cur_pix, new_ph.obj_id, new_pix);
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
*reload_lu = 1;
|
||||
} else if ((objix_pix_ph && data_pix_ph && data_pix_lu && objix_pix_lu == 0) ||
|
||||
|
@ -315,7 +332,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
|
|||
// rewrite as obj_id_lu
|
||||
new_ph.obj_id = lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG;
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: rewrite page %04x as %04x\n", cur_pix, new_ph.obj_id);
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
|
||||
res = spiffs_rewrite_page(fs, cur_pix, &new_ph, &new_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
*reload_lu = 1;
|
||||
|
@ -353,7 +370,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
|
|||
// if only data page exists, make this page index
|
||||
if (data_pix && objix_pix_d == 0) {
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: other data page exists, make this index\n");
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_INDEX, lu_obj_id, p_hdr->span_ix);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_INDEX, lu_obj_id, p_hdr->span_ix);
|
||||
spiffs_page_header new_ph;
|
||||
spiffs_page_ix new_pix;
|
||||
new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_INDEX);
|
||||
|
@ -369,7 +386,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
|
|||
// if only index exists, make data page
|
||||
if (data_pix == 0 && objix_pix_d) {
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: other index page exists, make this data\n");
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, lu_obj_id, p_hdr->span_ix);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, lu_obj_id, p_hdr->span_ix);
|
||||
spiffs_page_header new_ph;
|
||||
spiffs_page_ix new_pix;
|
||||
new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL);
|
||||
|
@ -406,7 +423,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
|
|||
// page referenced by object index but not final
|
||||
// just finalize
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: unfinalized page is referred, finalizing\n");
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
|
||||
u8_t flags = 0xff & ~SPIFFS_PH_FLAG_FINAL;
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + offsetof(spiffs_page_header, flags),
|
||||
|
@ -418,7 +435,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
|
|||
|
||||
if (delete_page) {
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: deleting page %04x\n", cur_pix);
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_PAGE, cur_pix, 0);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_PAGE, cur_pix, 0);
|
||||
res = spiffs_page_delete(fs, cur_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
|
@ -427,14 +444,14 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
|
|||
}
|
||||
|
||||
static s32_t spiffs_lookup_check_v(spiffs *fs, spiffs_obj_id obj_id, spiffs_block_ix cur_block, int cur_entry,
|
||||
u32_t user_data, void *user_p) {
|
||||
(void)user_data;
|
||||
(void)user_p;
|
||||
const void *user_const_p, void *user_var_p) {
|
||||
(void)user_const_p;
|
||||
(void)user_var_p;
|
||||
s32_t res = SPIFFS_OK;
|
||||
spiffs_page_header p_hdr;
|
||||
spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, cur_block, cur_entry);
|
||||
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS,
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS,
|
||||
(cur_block * 256)/fs->block_count, 0);
|
||||
|
||||
// load header
|
||||
|
@ -460,7 +477,7 @@ s32_t spiffs_lookup_consistency_check(spiffs *fs, u8_t check_all_objects) {
|
|||
(void)check_all_objects;
|
||||
s32_t res = SPIFFS_OK;
|
||||
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, 0, 0);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, 0, 0);
|
||||
|
||||
res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_lookup_check_v, 0, 0, 0, 0);
|
||||
|
||||
|
@ -469,10 +486,10 @@ s32_t spiffs_lookup_consistency_check(spiffs *fs, u8_t check_all_objects) {
|
|||
}
|
||||
|
||||
if (res != SPIFFS_OK) {
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_ERROR, res, 0);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_ERROR, res, 0);
|
||||
}
|
||||
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, 256, 0);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, 256, 0);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -506,14 +523,17 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
|
|||
spiffs_block_ix cur_block = 0;
|
||||
// build consistency bitmap for id range traversing all blocks
|
||||
while (!restart && cur_block < fs->block_count) {
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS,
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS,
|
||||
(pix_offset*256)/(SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count) +
|
||||
((((cur_block * pages_per_scan * 256)/ (SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count))) / fs->block_count),
|
||||
0);
|
||||
|
||||
// traverse each page except for lookup pages
|
||||
spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_PAGES(fs) + SPIFFS_PAGES_PER_BLOCK(fs) * cur_block;
|
||||
while (!restart && cur_pix < SPIFFS_PAGES_PER_BLOCK(fs) * (cur_block+1)) {
|
||||
//if ((cur_pix & 0xff) == 0)
|
||||
// SPIFFS_CHECK_DBG("PA: processing pix %08x, block %08x of pix %08x, block %08x\n",
|
||||
// cur_pix, cur_block, SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count, fs->block_count);
|
||||
|
||||
// read header
|
||||
spiffs_page_header p_hdr;
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
|
@ -598,11 +618,11 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
|
|||
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
|
||||
// index bad also, cannot mend this file
|
||||
SPIFFS_CHECK_DBG("PA: FIXUP: index bad %i, cannot mend - delete object\n", res);
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, objix_p_hdr->obj_id, 0);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, objix_p_hdr->obj_id, 0);
|
||||
// delete file
|
||||
res = spiffs_page_delete(fs, cur_pix);
|
||||
} else {
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, objix_p_hdr->obj_id, objix_p_hdr->span_ix);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, objix_p_hdr->obj_id, objix_p_hdr->span_ix);
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
restart = 1;
|
||||
|
@ -636,7 +656,7 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
|
|||
if (data_pix == 0) {
|
||||
// not found, this index is badly borked
|
||||
SPIFFS_CHECK_DBG("PA: FIXUP: index bad, delete object id %04x\n", p_hdr.obj_id);
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
|
||||
res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
break;
|
||||
|
@ -648,10 +668,10 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
|
|||
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
|
||||
// index bad also, cannot mend this file
|
||||
SPIFFS_CHECK_DBG("PA: FIXUP: index bad %i, cannot mend!\n", res);
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
|
||||
res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
|
||||
} else {
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, p_hdr.obj_id, p_hdr.span_ix);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, p_hdr.obj_id, p_hdr.span_ix);
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
restart = 1;
|
||||
|
@ -669,7 +689,7 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
|
|||
// the object which is referring to this page
|
||||
SPIFFS_CHECK_DBG("PA: FIXUP: removing object %04x and page %04x\n",
|
||||
p_hdr.obj_id, cur_pix);
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
|
||||
res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
// extra precaution, delete this page also
|
||||
|
@ -764,19 +784,19 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
|
|||
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
|
||||
// index bad also, cannot mend this file
|
||||
SPIFFS_CHECK_DBG("PA: FIXUP: index bad %i, cannot mend!\n", res);
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
|
||||
res = spiffs_page_delete(fs, cur_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
|
||||
} else {
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, p_hdr.obj_id, p_hdr.span_ix);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, p_hdr.obj_id, p_hdr.span_ix);
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
restart = 1;
|
||||
continue;
|
||||
} else if (delete_page) {
|
||||
SPIFFS_CHECK_DBG("PA: FIXUP: deleting page %04x\n", cur_pix);
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_PAGE, cur_pix, 0);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_PAGE, cur_pix, 0);
|
||||
res = spiffs_page_delete(fs, cur_pix);
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
@ -818,6 +838,8 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
SPIFFS_CHECK_DBG("PA: processed %04x, restart %i\n", pix_offset, restart);
|
||||
// next page range
|
||||
if (!restart) {
|
||||
pix_offset += pages_per_scan;
|
||||
|
@ -828,12 +850,12 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
|
|||
|
||||
// Checks consistency amongst all pages and fixes irregularities
|
||||
s32_t spiffs_page_consistency_check(spiffs *fs) {
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, 0, 0);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, 0, 0);
|
||||
s32_t res = spiffs_page_consistency_check_i(fs);
|
||||
if (res != SPIFFS_OK) {
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_ERROR, res, 0);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_ERROR, res, 0);
|
||||
}
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, 256, 0);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, 256, 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -855,14 +877,14 @@ static int spiffs_object_index_search(spiffs *fs, spiffs_obj_id obj_id) {
|
|||
}
|
||||
|
||||
static s32_t spiffs_object_index_consistency_check_v(spiffs *fs, spiffs_obj_id obj_id, spiffs_block_ix cur_block,
|
||||
int cur_entry, u32_t user_data, void *user_p) {
|
||||
(void)user_data;
|
||||
int cur_entry, const void *user_const_p, void *user_var_p) {
|
||||
(void)user_const_p;
|
||||
s32_t res_c = SPIFFS_VIS_COUNTINUE;
|
||||
s32_t res = SPIFFS_OK;
|
||||
u32_t *log_ix = (u32_t *)user_p;
|
||||
u32_t *log_ix = (u32_t*)user_var_p;
|
||||
spiffs_obj_id *obj_table = (spiffs_obj_id *)fs->work;
|
||||
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS,
|
||||
CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS,
|
||||
(cur_block * 256)/fs->block_count, 0);
|
||||
|
||||
if (obj_id != SPIFFS_OBJ_ID_FREE && obj_id != SPIFFS_OBJ_ID_DELETED && (obj_id & SPIFFS_OBJ_ID_IX_FLAG)) {
|
||||
|
@ -879,7 +901,7 @@ static s32_t spiffs_object_index_consistency_check_v(spiffs *fs, spiffs_obj_id o
|
|||
(SPIFFS_PH_FLAG_DELET)) {
|
||||
SPIFFS_CHECK_DBG("IX: pix %04x, obj id:%04x spix:%04x header not fully deleted - deleting\n",
|
||||
cur_pix, obj_id, p_hdr.span_ix);
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_INDEX, SPIFFS_CHECK_DELETE_PAGE, cur_pix, obj_id);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_DELETE_PAGE, cur_pix, obj_id);
|
||||
res = spiffs_page_delete(fs, cur_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
return res_c;
|
||||
|
@ -935,7 +957,7 @@ static s32_t spiffs_object_index_consistency_check_v(spiffs *fs, spiffs_obj_id o
|
|||
if (delete) {
|
||||
SPIFFS_CHECK_DBG("IX: FIXUP: pix %04x, obj id:%04x spix:%04x is orphan index - deleting\n",
|
||||
cur_pix, obj_id, p_hdr.span_ix);
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_INDEX, SPIFFS_CHECK_DELETE_ORPHANED_INDEX, cur_pix, obj_id);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_DELETE_ORPHANED_INDEX, cur_pix, obj_id);
|
||||
res = spiffs_page_delete(fs, cur_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
|
@ -958,16 +980,17 @@ s32_t spiffs_object_index_consistency_check(spiffs *fs) {
|
|||
// a reachable/unreachable object id.
|
||||
memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
|
||||
u32_t obj_id_log_ix = 0;
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, 0, 0);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, 0, 0);
|
||||
res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_object_index_consistency_check_v, 0, &obj_id_log_ix,
|
||||
0, 0);
|
||||
0, 0);
|
||||
if (res == SPIFFS_VIS_END) {
|
||||
res = SPIFFS_OK;
|
||||
}
|
||||
if (res != SPIFFS_OK) {
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_INDEX, SPIFFS_CHECK_ERROR, res, 0);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_ERROR, res, 0);
|
||||
}
|
||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, 256, 0);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, 256, 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
|
|
@ -8,26 +8,25 @@
|
|||
#ifndef SPIFFS_CONFIG_H_
|
||||
#define SPIFFS_CONFIG_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "nodemcu_spiffs.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
// compile time switches
|
||||
|
||||
// Set generic spiffs debug output call.
|
||||
#ifndef SPIFFS_DGB
|
||||
#ifndef SPIFFS_DBG
|
||||
#define SPIFFS_DBG(...) //printf(__VA_ARGS__)
|
||||
#endif
|
||||
// Set spiffs debug output call for garbage collecting.
|
||||
#ifndef SPIFFS_GC_DGB
|
||||
#ifndef SPIFFS_GC_DBG
|
||||
#define SPIFFS_GC_DBG(...) //printf(__VA_ARGS__)
|
||||
#endif
|
||||
// Set spiffs debug output call for caching.
|
||||
#ifndef SPIFFS_CACHE_DGB
|
||||
#ifndef SPIFFS_CACHE_DBG
|
||||
#define SPIFFS_CACHE_DBG(...) //printf(__VA_ARGS__)
|
||||
#endif
|
||||
// Set spiffs debug output call for system consistency checks.
|
||||
#ifndef SPIFFS_CHECK_DGB
|
||||
#ifndef SPIFFS_CHECK_DBG
|
||||
#define SPIFFS_CHECK_DBG(...) //printf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
|
@ -51,10 +50,8 @@
|
|||
|
||||
// Enable/disable statistics on caching. Debug/test purpose only.
|
||||
#ifndef SPIFFS_CACHE_STATS
|
||||
#define SPIFFS_CACHE_STATS 0
|
||||
#define SPIFFS_CACHE_STATS 1
|
||||
#endif
|
||||
#else
|
||||
#define SPIFFS_CACHE_WR 0
|
||||
#endif
|
||||
|
||||
// Always check header of each accessed page to ensure consistent state.
|
||||
|
@ -70,7 +67,7 @@
|
|||
|
||||
// Enable/disable statistics on gc. Debug/test purpose only.
|
||||
#ifndef SPIFFS_GC_STATS
|
||||
#define SPIFFS_GC_STATS 0
|
||||
#define SPIFFS_GC_STATS 1
|
||||
#endif
|
||||
|
||||
// Garbage collecting examines all pages in a block which and sums up
|
||||
|
@ -95,9 +92,11 @@
|
|||
#define SPIFFS_GC_HEUR_W_ERASE_AGE (50)
|
||||
#endif
|
||||
|
||||
// Object name maximum length.
|
||||
// Object name maximum length. Note that this length include the
|
||||
// zero-termination character, meaning maximum string of characters
|
||||
// can at most be CONFIG_SPIFFS_OBJ_NAME_LEN - 1.
|
||||
#ifndef SPIFFS_OBJ_NAME_LEN
|
||||
#define SPIFFS_OBJ_NAME_LEN (32)
|
||||
#define SPIFFS_OBJ_NAME_LEN (CONFIG_FS_OBJ_NAME_LEN+1)
|
||||
#endif
|
||||
|
||||
// Size of buffer allocated on stack used when copying data.
|
||||
|
@ -115,19 +114,29 @@
|
|||
#define SPIFFS_USE_MAGIC (0)
|
||||
#endif
|
||||
|
||||
#if SPIFFS_USE_MAGIC
|
||||
// Only valid when SPIFFS_USE_MAGIC is enabled. If SPIFFS_USE_MAGIC_LENGTH is
|
||||
// enabled, the magic will also be dependent on the length of the filesystem.
|
||||
// For example, a filesystem configured and formatted for 4 megabytes will not
|
||||
// be accepted for mounting with a configuration defining the filesystem as 2
|
||||
// megabytes.
|
||||
#ifndef SPIFFS_USE_MAGIC_LENGTH
|
||||
#define SPIFFS_USE_MAGIC_LENGTH (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level
|
||||
// These should be defined on a multithreaded system
|
||||
|
||||
// define this to entering a mutex if you're running on a multithreaded system
|
||||
// define this to enter a mutex if you're running on a multithreaded system
|
||||
#ifndef SPIFFS_LOCK
|
||||
#define SPIFFS_LOCK(fs)
|
||||
#endif
|
||||
// define this to exiting a mutex if you're running on a multithreaded system
|
||||
// define this to exit a mutex if you're running on a multithreaded system
|
||||
#ifndef SPIFFS_UNLOCK
|
||||
#define SPIFFS_UNLOCK(fs)
|
||||
#endif
|
||||
|
||||
|
||||
// Enable if only one spiffs instance with constant configuration will exist
|
||||
// on the target. This will reduce calculations, flash and memory accesses.
|
||||
// Parts of configuration must be defined below instead of at time of mount.
|
||||
|
@ -155,7 +164,41 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
// Set SPFIFS_TEST_VISUALISATION to non-zero to enable SPIFFS_vis function
|
||||
// Enable this if your target needs aligned data for index tables
|
||||
#ifndef SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
|
||||
#define SPIFFS_ALIGNED_OBJECT_INDEX_TABLES 0
|
||||
#endif
|
||||
|
||||
// Enable this if you want the HAL callbacks to be called with the spiffs struct
|
||||
#ifndef SPIFFS_HAL_CALLBACK_EXTRA
|
||||
#define SPIFFS_HAL_CALLBACK_EXTRA 0
|
||||
#endif
|
||||
|
||||
// Enable this if you want to add an integer offset to all file handles
|
||||
// (spiffs_file). This is useful if running multiple instances of spiffs on
|
||||
// same target, in order to recognise to what spiffs instance a file handle
|
||||
// belongs.
|
||||
// NB: This adds config field fh_ix_offset in the configuration struct when
|
||||
// mounting, which must be defined.
|
||||
#ifndef SPIFFS_FILEHDL_OFFSET
|
||||
#define SPIFFS_FILEHDL_OFFSET 0
|
||||
#endif
|
||||
|
||||
// Enable this to compile a read only version of spiffs.
|
||||
// This will reduce binary size of spiffs. All code comprising modification
|
||||
// of the file system will not be compiled. Some config will be ignored.
|
||||
// HAL functions for erasing and writing to spi-flash may be null. Cache
|
||||
// can be disabled for even further binary size reduction (and ram savings).
|
||||
// Functions modifying the fs will return SPIFFS_ERR_RO_NOT_IMPL.
|
||||
// If the file system cannot be mounted due to aborted erase operation and
|
||||
// SPIFFS_USE_MAGIC is enabled, SPIFFS_ERR_RO_ABORTED_OPERATION will be
|
||||
// returned.
|
||||
// Might be useful for e.g. bootloaders and such.
|
||||
#ifndef SPIFFS_READ_ONLY
|
||||
#define SPIFFS_READ_ONLY 0
|
||||
#endif
|
||||
|
||||
// Set SPIFFS_TEST_VISUALISATION to non-zero to enable SPIFFS_vis function
|
||||
// in the api. This function will visualize all filesystem using given printf
|
||||
// function.
|
||||
#ifndef SPIFFS_TEST_VISUALISATION
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#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;
|
||||
}
|
||||
|
||||
if (!SPIFFS_CHECK_MOUNT(fs)) {
|
||||
fs->err_code = SPIFFS_ERR_NOT_MOUNTED;
|
||||
return;
|
||||
}
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
#if SPIFFS_CACHE
|
||||
spiffs_fflush_cache(fs, fh);
|
||||
#endif
|
||||
spiffs_fd_return(fs, fh);
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
}
|
||||
|
||||
s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) {
|
||||
s32_t SPIFFS_close(spiffs *fs, spiffs_file fh) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
|
||||
s32_t res = SPIFFS_OK;
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
fh = SPIFFS_FH_UNOFFS(fs, fh);
|
||||
#if SPIFFS_CACHE
|
||||
res = spiffs_fflush_cache(fs, fh);
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
#endif
|
||||
res = spiffs_fd_return(fs, fh);
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
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,64 +1014,11 @@ s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used) {
|
|||
return res;
|
||||
}
|
||||
|
||||
s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) {
|
||||
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;
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return res;
|
||||
}
|
||||
|
||||
s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh) {
|
||||
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 == fd->size);
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return res;
|
||||
}
|
||||
|
||||
s32_t SPIFFS_size(spiffs *fs, spiffs_file fh) {
|
||||
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->size;
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return res;
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -924,10 +1029,15 @@ s32_t SPIFFS_gc_quick(spiffs *fs, u16_t max_free_pages) {
|
|||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return 0;
|
||||
#endif // SPIFFS_READ_ONLY
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
|
@ -938,8 +1048,61 @@ s32_t SPIFFS_gc(spiffs *fs, u32_t size) {
|
|||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return 0;
|
||||
#endif // SPIFFS_READ_ONLY
|
||||
}
|
||||
|
||||
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;
|
||||
res = spiffs_fd_get(fs, fh, &fd);
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
|
||||
#if SPIFFS_CACHE_WR
|
||||
res = spiffs_fflush_cache(fs, fh);
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
#endif
|
||||
|
||||
res = (fd->fdoffset >= (fd->size == SPIFFS_UNDEFINED_LEN ? 0 : fd->size));
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return res;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
fh = SPIFFS_FH_UNOFFS(fs, fh);
|
||||
|
||||
spiffs_fd *fd;
|
||||
res = spiffs_fd_get(fs, fh, &fd);
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
|
||||
#if SPIFFS_CACHE_WR
|
||||
res = spiffs_fflush_cache(fs, fh);
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
#endif
|
||||
|
||||
res = fd->fdoffset;
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return 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) {
|
||||
|
@ -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
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#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));
|
||||
SPIFFS_CHECK_RES(res);
|
||||
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
|
||||
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);
|
||||
// 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);
|
||||
|
||||
// ---------------
|
||||
|
|
Loading…
Reference in New Issue