2016-09-22 09:18:22 +02:00
|
|
|
// Module for interfacing with file system
|
|
|
|
|
|
|
|
#include "module.h"
|
|
|
|
#include "lauxlib.h"
|
|
|
|
#include "platform.h"
|
2021-10-20 12:24:09 +02:00
|
|
|
#include "esp_spiffs.h"
|
2016-09-22 09:18:22 +02:00
|
|
|
|
|
|
|
#include <string.h>
|
2021-10-20 12:24:09 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <dirent.h>
|
2022-01-01 07:36:48 +01:00
|
|
|
#include <errno.h>
|
2016-09-22 09:18:22 +02:00
|
|
|
|
2021-10-20 12:24:09 +02:00
|
|
|
static const char *default_fs_label =
|
|
|
|
((CONFIG_NODEMCU_DEFAULT_SPIFFS_LABEL &&
|
|
|
|
(CONFIG_NODEMCU_DEFAULT_SPIFFS_LABEL)[0]) ?
|
|
|
|
CONFIG_NODEMCU_DEFAULT_SPIFFS_LABEL : NULL);
|
2018-10-29 07:09:41 +01:00
|
|
|
|
|
|
|
|
2016-09-22 09:18:22 +02:00
|
|
|
// Lua: format()
|
|
|
|
static int file_format( lua_State* L )
|
|
|
|
{
|
2021-10-20 12:24:09 +02:00
|
|
|
if(esp_spiffs_format(default_fs_label) != ESP_OK)
|
2016-09-22 09:18:22 +02:00
|
|
|
{
|
|
|
|
NODE_ERR( "\n*** ERROR ***: unable to format. FS might be compromised.\n" );
|
|
|
|
NODE_ERR( "It is advised to re-flash the NodeMCU image.\n" );
|
|
|
|
luaL_error(L, "Failed to format file system");
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
NODE_ERR( "format done.\n" );
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Lua: list()
|
|
|
|
static int file_list( lua_State* L )
|
|
|
|
{
|
2022-11-06 14:29:03 +01:00
|
|
|
const char *dirname = luaL_optstring(L, 1, NULL);
|
|
|
|
|
2021-10-20 12:24:09 +02:00
|
|
|
DIR *dir;
|
2022-11-06 14:29:03 +01:00
|
|
|
if ((dir = opendir(dirname ? dirname : "/"))) {
|
2016-09-22 09:18:22 +02:00
|
|
|
lua_newtable( L );
|
2021-10-20 12:24:09 +02:00
|
|
|
struct dirent *e;
|
|
|
|
while ((e = readdir(dir))) {
|
2022-11-06 14:29:03 +01:00
|
|
|
char *fname = NULL;
|
|
|
|
if (dirname) {
|
|
|
|
asprintf(&fname, "%s/%s", dirname, e->d_name);
|
|
|
|
if (!fname) {
|
|
|
|
closedir(dir);
|
|
|
|
return luaL_error(L, "no memory");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
fname = e->d_name;
|
|
|
|
}
|
2021-10-20 12:24:09 +02:00
|
|
|
struct stat st = { 0, };
|
2022-11-06 14:29:03 +01:00
|
|
|
int err = stat(fname, &st);
|
|
|
|
if (err) {
|
|
|
|
// We historically ignored this error, so just warn (although it
|
|
|
|
// shouldn't really happen now).
|
|
|
|
NODE_ERR("Failed to stat %s err=%d\n", fname, err);
|
|
|
|
}
|
|
|
|
if (dirname) {
|
|
|
|
free(fname);
|
|
|
|
}
|
2021-10-20 12:24:09 +02:00
|
|
|
lua_pushinteger(L, st.st_size);
|
|
|
|
lua_setfield(L, -2, e->d_name);
|
2016-09-22 09:18:22 +02:00
|
|
|
}
|
2021-10-20 12:24:09 +02:00
|
|
|
closedir(dir);
|
2016-09-22 09:18:22 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Lua: exists(filename)
|
|
|
|
static int file_exists( lua_State* L )
|
|
|
|
{
|
|
|
|
size_t len;
|
|
|
|
const char *fname = luaL_checklstring( L, 1, &len );
|
|
|
|
|
2021-10-20 12:24:09 +02:00
|
|
|
struct stat st;
|
|
|
|
lua_pushboolean(L, stat(fname, &st) == 0 ? 1 : 0);
|
2016-09-22 09:18:22 +02:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2021-10-20 12:24:09 +02:00
|
|
|
|
2016-09-22 09:18:22 +02:00
|
|
|
// Lua: remove(filename)
|
|
|
|
static int file_remove( lua_State* L )
|
|
|
|
{
|
|
|
|
size_t len;
|
|
|
|
const char *fname = luaL_checklstring( L, 1, &len );
|
2021-10-20 12:24:09 +02:00
|
|
|
unlink(fname);
|
2016-09-22 09:18:22 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Lua: rename("oldname", "newname")
|
|
|
|
static int file_rename( lua_State* L )
|
|
|
|
{
|
2021-10-20 12:24:09 +02:00
|
|
|
const char *oldname = luaL_checkstring( L, 1);
|
|
|
|
const char *newname = luaL_checkstring( L, 2);
|
|
|
|
if (rename(oldname, newname) == 0) {
|
2016-09-22 09:18:22 +02:00
|
|
|
lua_pushboolean(L, 1);
|
|
|
|
} else {
|
|
|
|
lua_pushboolean(L, 0);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Lua: fsinfo()
|
|
|
|
static int file_fsinfo( lua_State* L )
|
|
|
|
{
|
2021-10-20 12:24:09 +02:00
|
|
|
size_t total, used;
|
|
|
|
if (esp_spiffs_info(default_fs_label, &total, &used) != ESP_OK)
|
|
|
|
return luaL_error(L, "spiffs file system not mounted");
|
|
|
|
|
2016-09-22 09:18:22 +02:00
|
|
|
if(total>0x7FFFFFFF || used>0x7FFFFFFF || used > total)
|
|
|
|
{
|
|
|
|
return luaL_error(L, "file system error");
|
|
|
|
}
|
|
|
|
lua_pushinteger(L, total-used);
|
|
|
|
lua_pushinteger(L, used);
|
|
|
|
lua_pushinteger(L, total);
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
|
2018-10-29 07:09:41 +01:00
|
|
|
|
2022-01-01 07:36:48 +01:00
|
|
|
static int file_mkdir( lua_State *L )
|
|
|
|
{
|
|
|
|
const char *name = luaL_checkstring(L, 1);
|
|
|
|
unsigned mode = luaL_optint(L, 2, 0777);
|
|
|
|
if (mkdir(name, mode) != 0) {
|
|
|
|
return
|
|
|
|
luaL_error(L, "failed to create directory '%s'; code %d", name, errno);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int file_rmdir( lua_State *L )
|
|
|
|
{
|
|
|
|
const char *name = luaL_checkstring(L, 1);
|
|
|
|
if (rmdir(name) != 0) {
|
|
|
|
return
|
|
|
|
luaL_error(L, "failed to remove directory '%s'; code %d", name, errno);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-22 09:18:22 +02:00
|
|
|
// Module function map
|
2021-08-21 17:39:54 +02:00
|
|
|
LROT_BEGIN(file, NULL, 0)
|
2019-07-22 11:13:43 +02:00
|
|
|
LROT_FUNCENTRY( list, file_list )
|
|
|
|
LROT_FUNCENTRY( format, file_format )
|
|
|
|
LROT_FUNCENTRY( remove, file_remove )
|
|
|
|
LROT_FUNCENTRY( rename, file_rename )
|
|
|
|
LROT_FUNCENTRY( exists, file_exists )
|
|
|
|
LROT_FUNCENTRY( fsinfo, file_fsinfo )
|
2022-01-01 07:36:48 +01:00
|
|
|
LROT_FUNCENTRY( mkdir, file_mkdir )
|
|
|
|
LROT_FUNCENTRY( rmdir, file_rmdir )
|
2019-07-22 11:13:43 +02:00
|
|
|
LROT_END(file, NULL, 0)
|
2016-09-22 09:18:22 +02:00
|
|
|
|
2018-10-29 07:09:41 +01:00
|
|
|
|
2021-10-20 12:24:09 +02:00
|
|
|
NODEMCU_MODULE(FILE, "file", file, NULL);
|