nodemcu-firmware/components/modules/file.c

175 lines
3.9 KiB
C
Raw Normal View History

// Module for interfacing with file system
#include "module.h"
#include "lauxlib.h"
#include "platform.h"
#include "esp_spiffs.h"
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
static const char *default_fs_label =
((CONFIG_NODEMCU_DEFAULT_SPIFFS_LABEL &&
(CONFIG_NODEMCU_DEFAULT_SPIFFS_LABEL)[0]) ?
CONFIG_NODEMCU_DEFAULT_SPIFFS_LABEL : NULL);
// Lua: format()
static int file_format( lua_State* L )
{
if(esp_spiffs_format(default_fs_label) != ESP_OK)
{
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" );
}
const char *err = platform_remount_default_fs(false);
if (err)
return luaL_error(L, err);
return 0;
}
// Lua: list()
static int file_list( lua_State* L )
{
const char *dirname = luaL_optstring(L, 1, NULL);
DIR *dir;
if ((dir = opendir(dirname ? dirname : "/"))) {
lua_newtable( L );
struct dirent *e;
while ((e = readdir(dir))) {
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;
}
struct stat st = { 0, };
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);
}
lua_pushinteger(L, st.st_size);
lua_setfield(L, -2, e->d_name);
}
closedir(dir);
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 );
struct stat st;
lua_pushboolean(L, stat(fname, &st) == 0 ? 1 : 0);
return 1;
}
// Lua: remove(filename)
static int file_remove( lua_State* L )
{
size_t len;
const char *fname = luaL_checklstring( L, 1, &len );
unlink(fname);
return 0;
}
// Lua: rename("oldname", "newname")
static int file_rename( lua_State* L )
{
const char *oldname = luaL_checkstring( L, 1);
const char *newname = luaL_checkstring( L, 2);
if (rename(oldname, newname) == 0) {
lua_pushboolean(L, 1);
} else {
lua_pushboolean(L, 0);
}
return 1;
}
// Lua: fsinfo()
static int file_fsinfo( lua_State* L )
{
size_t total, used;
if (esp_spiffs_info(default_fs_label, &total, &used) != ESP_OK)
return luaL_error(L, "spiffs file system not mounted");
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;
}
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;
}
// Module function map
LROT_BEGIN(file, NULL, 0)
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 )
LROT_FUNCENTRY( mkdir, file_mkdir )
LROT_FUNCENTRY( rmdir, file_rmdir )
LROT_END(file, NULL, 0)
NODEMCU_MODULE(FILE, "file", file, NULL);