blob: 44500d9cd73c613512c7001d7152923eaeda3cfc [file] [log] [blame]
// Forth interfaces to SPIFFS FLASH filesystem
#include "forth.h"
#include "compiler.h"
#include "stdio.h"
#include "esp_stdint.h"
#include "arch/cc.h"
#define NODEMCU_SPIFFS_NO_INCLUDE // Prevents stdint type collisions
#include "spiffs.h"
extern spiffs fs;
void read_dictionary(char *name, cell *up) { FTHERROR("No file I/O\n"); }
void write_dictionary(char *name, int len, char *dict, int dictsize,
cell *up, int usersize)
{
FTHERROR("No file I/O\n");
}
#define MAXNAMELEN 64
cell pfflush(cell f, cell *up) {
return SPIFFS_fflush(&fs, (spiffs_file)f);
}
cell pfsize(cell f, u_cell *high, u_cell *low, cell *up) {
int32_t curpos = SPIFFS_tell(&fs, (spiffs_file)f);
int32_t size = SPIFFS_lseek(&fs, (spiffs_file)f, 0, SPIFFS_SEEK_END);
(void) SPIFFS_lseek(&fs, (spiffs_file)f, curpos, SPIFFS_SEEK_SET);
*high = 0;
*low = size;
return (cell)0; // SPIFFS_tell has no error returns
}
void pfmarkinput(void *fp, cell *up) {}
void pfprint_input_stack(void) {}
static spiffs_flags open_modes[] = { SPIFFS_RDONLY, SPIFFS_WRONLY, SPIFFS_RDWR };
cell pfopen(char *name, int len, int mode, cell *up) {
char cstrbuf[MAXNAMELEN];
char *s = altocstr(name, len, cstrbuf, MAXNAMELEN);
cell ret = SPIFFS_open(&fs, s, (spiffs_flags)open_modes[mode], 0);
// spiffs returns negative number on error, like Unix open(),
// but pfopen() is supposed to return NULL like fopen()
return ret<0 ? 0 : ret ;
}
static spiffs_flags create_modes[] = { SPIFFS_CREAT|SPIFFS_APPEND|SPIFFS_RDWR, SPIFFS_CREAT|SPIFFS_TRUNC|SPIFFS_WRONLY, SPIFFS_CREAT|SPIFFS_TRUNC|SPIFFS_RDWR };
cell pfcreate(char *name, int len, int mode, cell *up) {
char cstrbuf[MAXNAMELEN];
char *s = altocstr(name, len, cstrbuf, MAXNAMELEN);
cell ret = SPIFFS_open(&fs, s, (spiffs_flags)create_modes[mode], 0);
// spiffs returns negative number on error, like Unix open(),
// but pfopen() is supposed to return NULL like fopen()
return ret<0 ? 0 : ret ;
}
cell pfclose(cell fd, cell *up) {
return SPIFFS_close(&fs, (spiffs_file)fd);
}
cell freadline(cell f, cell *sp, cell *up) /* Returns IO result */
{
// Stack: adr len -- actual more?
u_char *adr = (u_char *)sp[1];
register cell len = sp[0];
cell actual;
u_char c;
int err;
sp[0] = -1; // Assume not end of file
SPIFFS_clearerr(&fs);
for (actual = 0; actual < len; ) {
if ((err = SPIFFS_errno(&fs) != 0)) {
sp[1] = actual;
sp[0] = err;
return(READFAIL);
}
if (SPIFFS_eof(&fs, (spiffs_file)f)) {
if (actual == 0)
sp[0] = 0;
break;
}
if (SPIFFS_read(&fs, (spiffs_file)f, &c, 1) != 1) {
if (actual == 0)
sp[0] = 0;
break;
}
if (c == CNEWLINE) { // Last character of an end-of-line sequence
break;
}
// Don't store the first half of a 2-character newline sequence
if (c == SNEWLINE[0])
continue;
*adr++ = c;
++actual;
}
sp[1] = actual;
return(0);
}
cell
pfread(cell *sp, cell len, void *fid, cell *up) // Returns IO result, actual in *sp
{
*sp = (cell)SPIFFS_read(&fs, (spiffs_file)(int)fid, (void *)*sp, (size_t)len);
if (*sp < 0) {
*sp = 0;
cell ret = (cell)SPIFFS_errno(&fs);
SPIFFS_clearerr(&fs);
return ret;
}
return 0;
}
cell
pfwrite(void *adr, cell len, void *fid, cell *up)
{
cell ret = (cell)SPIFFS_write(&fs, (spiffs_file)(int)fid, adr, (size_t)len);
if (ret < 0) {
return SPIFFS_errno(&fs);
}
return 0;
}
cell
pfseek(void *fid, u_cell high, u_cell low, cell *up)
{
(void)SPIFFS_lseek(&fs, (spiffs_file)(int)fid, low, 0);
return 0;
}
cell
pfposition(void *fid, u_cell *high, u_cell *low, cell *up)
{
*low = SPIFFS_tell(&fs, (spiffs_file)(int)fid);
*high = 0;
return 0;
}
void clear_log(cell *up) { }
void start_logging(cell *up) { }
void stop_logging(cell *up) { }
cell log_extent(cell *log_base, cell *up) { *log_base = 0; return 0; }
extern spiffs fs;
void rename_file(char *new, char *old)
{
SPIFFS_rename(&fs, old, new);
}
cell fs_avail(void)
{
u32_t total, used;
SPIFFS_info(&fs, &total, &used);
return (cell)(total - used);
}
void delete_file(char *path)
{
SPIFFS_remove(&fs, path);
}
static struct spiffs_dirent dirent;
static spiffs_DIR dir;
struct spiffs_dirent *next_file(void)
{
struct spiffs_dirent *dp = &dirent;
while ((dp = SPIFFS_readdir(&dir, dp)) != NULL) {
if (dp->type == SPIFFS_TYPE_FILE) {
return dp;
}
}
return 0;
}
struct spiffs_dirent *first_file(void)
{
if (SPIFFS_opendir(&fs, "", &dir))
return next_file();
return 0;
}
cell dirent_size(struct spiffs_dirent *d)
{
return d->size;
}
cell dirent_name(struct spiffs_dirent *d)
{
return (cell)(d->name);
}