From 889b167a6bae322bdd759961944d0bfb0cad1a66 Mon Sep 17 00:00:00 2001 From: rxi Date: Fri, 14 Oct 2016 23:01:18 +0100 Subject: [PATCH] Added write functionality to filesystem --- src/embed/boot.lua | 4 ++ src/filesystem.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++ src/filesystem.h | 17 +++++--- 3 files changed, 111 insertions(+), 6 deletions(-) diff --git a/src/embed/boot.lua b/src/embed/boot.lua index 114f11b..1899e21 100644 --- a/src/embed/boot.lua +++ b/src/embed/boot.lua @@ -21,6 +21,10 @@ function love.boot() end end + -- Set write directory and mount + love.filesystem.setWriteDir("save") + love.filesystem.mount("save") + -- Load main.lua or init `nogame` state if love.filesystem.isFile("main.lua") then require("main") diff --git a/src/filesystem.c b/src/filesystem.c index e961418..7ffabe6 100644 --- a/src/filesystem.c +++ b/src/filesystem.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "luaobj.h" #include "lib/microtar/microtar.h" @@ -39,6 +40,7 @@ struct Mount { int filesystem_mountIdx; Mount filesystem_mounts[MAX_MOUNTS]; +char filesystem_writeDir[MAX_PATH]; #define FOREACH_MOUNT(var)\ for (Mount *var = &filesystem_mounts[filesystem_mountIdx - 1];\ @@ -111,6 +113,36 @@ static void strip_trailing_slash(char *str) { } +static int is_separator(int chr) { + return (chr == '/' || chr == '\\'); +} + + +static int make_dirs(const char *path) { + char str[MAX_PATH]; + char *p = str; + int err = concat_path(str, path, ""); + if (err) { + return err; + } + if (p[0] == '/') p++; + if (p[0] && p[1] == ':' && p[2] == '\\') p += 3; + while (*p) { + if (is_separator(*p)) { + *p = '\0'; + if (get_file_type(str) != FILESYSTEM_TDIR) { + if (mkdir(str, S_IRWXU) == -1) { + return FILESYSTEM_EMKDIRFAIL; + } + } + *p = '/'; + } + p++; + } + return FILESYSTEM_ESUCCESS; +} + + /*==================*/ /* Directory Mount */ /*==================*/ @@ -399,6 +431,9 @@ const char* filesystem_strerror(int err) { case FILESYSTEM_EMOUNTED : return "path already mounted"; case FILESYSTEM_ENOMOUNT : return "path is not mounted"; case FILESYSTEM_EMOUNTFAIL : return "could not mount path"; + case FILESYSTEM_ENOWRITEDIR : return "no write directory set"; + case FILESYSTEM_EWRITEFAIL : return "could not write file"; + case FILESYSTEM_EMKDIRFAIL : return "could not make directory"; } return "unknown error"; } @@ -507,6 +542,39 @@ void filesystem_free(void *ptr) { } +int filesystem_setWriteDir(const char *path) { + if (strlen(path) >= MAX_PATH) { + return FILESYSTEM_ETOOLONG; + } + int err = make_dirs(path); + if (err) { + return err; + } + strcpy(filesystem_writeDir, path); + return FILESYSTEM_ESUCCESS; +} + + +int filesystem_write(const char *filename, const void *data, int size) { + int err, n; + char buf[MAX_PATH]; + if (!*filesystem_writeDir) { + return FILESYSTEM_ENOWRITEDIR; + } + err = concat_path(buf, filesystem_writeDir, filename); + if (err) { + return err; + } + FILE *fp = fopen(buf, "wb"); + if (!fp) { + return FILESYSTEM_EWRITEFAIL; + } + n = fwrite(data, 1, size, fp); + fclose(fp); + return n == size ? FILESYSTEM_ESUCCESS : FILESYSTEM_EWRITEFAIL; +} + + /*==================*/ /* Lua Binds */ /*==================*/ @@ -571,6 +639,32 @@ int l_filesystem_read(lua_State *L) { } +int l_filesystem_setWriteDir(lua_State *L) { + const char *path = luaL_checkstring(L, 1); + int err = filesystem_setWriteDir(path); + if (err) { + lua_pushnil(L); + lua_pushstring(L, filesystem_strerror(err)); + return 2; + } + lua_pushboolean(L, 1); + return 1; +} + + +int l_filesystem_write(lua_State *L) { + size_t sz; + const char *filename = luaL_checkstring(L, 1); + const char *data = luaL_tolstring(L, 2, &sz); + int err = filesystem_write(filename, data, sz); + if (err) { + luaL_error(L, "%s", filesystem_strerror(err)); + } + lua_pushboolean(L, 1); + return 1; +} + + int luaopen_filesystem(lua_State *L) { luaL_Reg reg[] = { { "mount", l_filesystem_mount }, @@ -579,6 +673,8 @@ int luaopen_filesystem(lua_State *L) { { "isFile", l_filesystem_isFile }, { "isDirectory", l_filesystem_isDirectory }, { "read", l_filesystem_read }, + { "setWriteDir", l_filesystem_setWriteDir }, + { "write", l_filesystem_write }, { 0, 0 }, }; luaL_newlib(L, reg); diff --git a/src/filesystem.h b/src/filesystem.h index 61e2fad..a9be65d 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -13,12 +13,15 @@ #include enum { - FILESYSTEM_ESUCCESS = 0, - FILESYSTEM_EFAILURE = -1, - FILESYSTEM_ETOOLONG = -2, - FILESYSTEM_EMOUNTED = -3, - FILESYSTEM_ENOMOUNT = -4, - FILESYSTEM_EMOUNTFAIL = -5 + FILESYSTEM_ESUCCESS = 0, + FILESYSTEM_EFAILURE = -1, + FILESYSTEM_ETOOLONG = -2, + FILESYSTEM_EMOUNTED = -3, + FILESYSTEM_ENOMOUNT = -4, + FILESYSTEM_EMOUNTFAIL = -5, + FILESYSTEM_ENOWRITEDIR = -6, + FILESYSTEM_EWRITEFAIL = -7, + FILESYSTEM_EMKDIRFAIL = -8 }; const char* filesystem_strerror(int err); @@ -30,5 +33,7 @@ int filesystem_isFile(const char *filename); int filesystem_isDirectory(const char *filename); void* filesystem_read(const char *filename, int *size); void filesystem_free(void *ptr); +int filesystem_setWriteDir(const char *path); +int filesystem_write(const char *filename, const void *data, int size); #endif