/*
* lua file helpers functions
*
* (C) 2016 M. Liebmann (micha-bbg)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "luainstance.h"
#include "lua_filehelpers.h"
CLuaInstFileHelpers* CLuaInstFileHelpers::getInstance()
{
static CLuaInstFileHelpers* LuaInstFileHelpers = NULL;
if (!LuaInstFileHelpers)
LuaInstFileHelpers = new CLuaInstFileHelpers();
return LuaInstFileHelpers;
}
CLuaFileHelpers *CLuaInstFileHelpers::FileHelpersCheckData(lua_State *L, int n)
{
return *(CLuaFileHelpers **) luaL_checkudata(L, n, LUA_FILEHELPER_CLASSNAME);
}
void CLuaInstFileHelpers::LuaFileHelpersRegister(lua_State *L)
{
luaL_Reg meth[] = {
{ "new", CLuaInstFileHelpers::FileHelpersNew },
{ "cp", CLuaInstFileHelpers::FileHelpersCp },
{ "chmod", CLuaInstFileHelpers::FileHelpersChmod },
{ "touch", CLuaInstFileHelpers::FileHelpersTouch },
{ "rmdir", CLuaInstFileHelpers::FileHelpersRmdir },
{ "mkdir", CLuaInstFileHelpers::FileHelpersMkdir },
{ "readlink", CLuaInstFileHelpers::FileHelpersReadlink },
{ "ln", CLuaInstFileHelpers::FileHelpersLn },
{ "exist", CLuaInstFileHelpers::FileHelpersExist },
{ "__gc", CLuaInstFileHelpers::FileHelpersDelete },
{ NULL, NULL }
};
luaL_newmetatable(L, LUA_FILEHELPER_CLASSNAME);
luaL_setfuncs(L, meth, 0);
lua_pushvalue(L, -1);
lua_setfield(L, -1, "__index");
lua_setglobal(L, LUA_FILEHELPER_CLASSNAME);
}
int CLuaInstFileHelpers::FileHelpersNew(lua_State *L)
{
CLuaFileHelpers **udata = (CLuaFileHelpers **) lua_newuserdata(L, sizeof(CLuaFileHelpers *));
*udata = new CLuaFileHelpers();
luaL_getmetatable(L, LUA_FILEHELPER_CLASSNAME);
lua_setmetatable(L, -2);
return 1;
}
int CLuaInstFileHelpers::FileHelpersCp(lua_State *L)
{
CLuaFileHelpers *D = FileHelpersCheckData(L, 1);
if (!D) return 0;
int numargs = lua_gettop(L) - 1;
int min_numargs = 2;
if (numargs < min_numargs) {
printf("luascript cp: not enough arguments (%d, expected %d)\n", numargs, min_numargs);
lua_pushboolean(L, false);
return 1;
}
if (!lua_isstring(L, 2)) {
printf("luascript cp: argument 1 is not a string.\n");
lua_pushboolean(L, false);
return 1;
}
const char *from = "";
from = luaL_checkstring(L, 2);
if (!lua_isstring(L, 3)) {
printf("luascript cp: argument 2 is not a string.\n");
lua_pushboolean(L, false);
return 1;
}
const char *to = "";
to = luaL_checkstring(L, 3);
const char *flags = "";
if (numargs > min_numargs)
flags = luaL_checkstring(L, 4);
bool ret = false;
CFileHelpers fh;
fh.setConsoleQuiet(true);
ret = fh.cp(from, to, flags);
if (ret == false) {
helpersDebugInfo di;
fh.readDebugInfo(&di);
lua_Debug ar;
lua_getstack(L, 1, &ar);
lua_getinfo(L, "Sl", &ar);
printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n",
ar.short_src, ar.currentline, di.msg.c_str(), di.file.c_str(), di.line);
}
lua_pushboolean(L, ret);
return 1;
}
int CLuaInstFileHelpers::FileHelpersChmod(lua_State *L)
{
CLuaFileHelpers *D = FileHelpersCheckData(L, 1);
if (!D) return 0;
int numargs = lua_gettop(L) - 1;
int min_numargs = 2;
if (numargs < min_numargs) {
printf("luascript chmod: not enough arguments (%d, expected %d)\n", numargs, min_numargs);
lua_pushboolean(L, false);
return 1;
}
const char *file = "";
file = luaL_checkstring(L, 2);
int mode_i = luaL_checkint(L, 3);
/* Hack for convert lua number to octal */
std::string mode_s = itoa(mode_i, 10);
mode_t mode = (mode_t)(strtol(mode_s.c_str(), (char **)NULL, 8) & 0x0FFF);
//printf("\n##### [%s:%d] str: %s, okt: %o \n \n", __func__, __LINE__, mode_s.c_str(), (int)mode);
bool ret = true;
if (chmod(file, mode) != 0) {
ret = false;
lua_Debug ar;
lua_getstack(L, 1, &ar);
lua_getinfo(L, "Sl", &ar);
const char* s = strerror(errno);
printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n",
ar.short_src, ar.currentline, s, __path_file__, __LINE__);
}
lua_pushboolean(L, ret);
return 1;
}
int CLuaInstFileHelpers::FileHelpersTouch(lua_State *L)
{
CLuaFileHelpers *D = FileHelpersCheckData(L, 1);
if (!D) return 0;
int numargs = lua_gettop(L) - 1;
int min_numargs = 1;
if (numargs < min_numargs) {
printf("luascript touch: not enough arguments (%d, expected %d)\n", numargs, min_numargs);
lua_pushboolean(L, false);
return 1;
}
const char *file = "";
file = luaL_checkstring(L, 2);
bool ret = true;
lua_Debug ar;
if (!file_exists(file)) {
FILE *f = fopen(file, "w");
if (f == NULL) {
ret = false;
lua_getstack(L, 1, &ar);
lua_getinfo(L, "Sl", &ar);
const char* s = strerror(errno);
printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n",
ar.short_src, ar.currentline, s, __path_file__, __LINE__);
lua_pushboolean(L, ret);
return 1;
}
fclose(f);
if (numargs == min_numargs) {
lua_pushboolean(L, ret);
return 1;
}
}
time_t modTime;
if (numargs == min_numargs)
/* current time */
modTime = time(NULL);
else
/* new time */
modTime = (time_t)luaL_checkint(L, 3);
utimbuf utb;
utb.actime = modTime;
utb.modtime = modTime;
if (utime(file, &utb) != 0) {
ret = false;
lua_getstack(L, 1, &ar);
lua_getinfo(L, "Sl", &ar);
const char* s = strerror(errno);
printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n",
ar.short_src, ar.currentline, s, __path_file__, __LINE__);
}
lua_pushboolean(L, ret);
return 1;
}
int CLuaInstFileHelpers::FileHelpersRmdir(lua_State *L)
{
CLuaFileHelpers *D = FileHelpersCheckData(L, 1);
if (!D) return 0;
int numargs = lua_gettop(L) - 1;
int min_numargs = 1;
if (numargs < min_numargs) {
printf("luascript rmdir: not enough arguments (%d, expected %d)\n", numargs, min_numargs);
lua_pushboolean(L, false);
return 1;
}
const char *dir = "";
dir = luaL_checkstring(L, 2);
bool ret = false;
CFileHelpers* fh = CFileHelpers::getInstance();
fh->setConsoleQuiet(true);
ret = fh->removeDir(dir);
if (ret == false) {
helpersDebugInfo di;
fh->readDebugInfo(&di);
lua_Debug ar;
lua_getstack(L, 1, &ar);
lua_getinfo(L, "Sl", &ar);
printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n",
ar.short_src, ar.currentline, di.msg.c_str(), di.file.c_str(), di.line);
}
lua_pushboolean(L, ret);
return 1;
}
int CLuaInstFileHelpers::FileHelpersMkdir(lua_State *L)
{
CLuaFileHelpers *D = FileHelpersCheckData(L, 1);
if (!D) return 0;
int numargs = lua_gettop(L) - 1;
int min_numargs = 1;
if (numargs < min_numargs) {
printf("luascript mkdir: not enough arguments (%d, expected %d)\n", numargs, min_numargs);
lua_pushboolean(L, false);
return 1;
}
const char *dir = "";
dir = luaL_checkstring(L, 2);
mode_t mode = 0755;
if (numargs > min_numargs) {
int mode_i = luaL_checkint(L, 3);
/* Hack for convert lua number to octal */
std::string mode_s = itoa(mode_i, 10);
mode = (mode_t)(strtol(mode_s.c_str(), (char **)NULL, 8) & 0x0FFF);
//printf("\n##### [%s:%d] str: %s, okt: %o \n \n", __func__, __LINE__, mode_s.c_str(), (int)mode);
}
bool ret = false;
CFileHelpers* fh = CFileHelpers::getInstance();
fh->setConsoleQuiet(true);
ret = fh->createDir(dir, mode);
if (ret == false) {
helpersDebugInfo di;
fh->readDebugInfo(&di);
lua_Debug ar;
lua_getstack(L, 1, &ar);
lua_getinfo(L, "Sl", &ar);
printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n",
ar.short_src, ar.currentline, di.msg.c_str(), di.file.c_str(), di.line);
}
lua_pushboolean(L, ret);
return 1;
}
int CLuaInstFileHelpers::FileHelpersReadlink(lua_State *L)
{
CLuaFileHelpers *D = FileHelpersCheckData(L, 1);
if (!D) return 0;
int numargs = lua_gettop(L) - 1;
int min_numargs = 1;
if (numargs < min_numargs) {
printf("luascript readlink: not enough arguments (%d, expected %d)\n", numargs, min_numargs);
lua_pushnil(L);
return 1;
}
const char *link = "";
link = luaL_checkstring(L, 2);
char buf[PATH_MAX];
memset(buf, '\0', sizeof(buf));
if (readlink(link, buf, sizeof(buf)-1) == -1) {
lua_Debug ar;
lua_getstack(L, 1, &ar);
lua_getinfo(L, "Sl", &ar);
const char* s = strerror(errno);
printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n",
ar.short_src, ar.currentline, s, __path_file__, __LINE__);
lua_pushnil(L);
return 1;
}
lua_pushstring(L, buf);
return 1;
}
int CLuaInstFileHelpers::FileHelpersLn(lua_State *L)
{
CLuaFileHelpers *D = FileHelpersCheckData(L, 1);
if (!D) return 0;
int numargs = lua_gettop(L) - 1;
int min_numargs = 2;
if (numargs < min_numargs) {
printf("luascript ln: not enough arguments (%d, expected %d)\n", numargs, min_numargs);
lua_pushboolean(L, false);
return 1;
}
const char *src = "";
src = luaL_checkstring(L, 2);
const char *link = "";
link = luaL_checkstring(L, 3);
const char *flags = "";
if (numargs > min_numargs)
flags = luaL_checkstring(L, 4);
bool symlnk = (strchr(flags, 's') != NULL);
bool force = (strchr(flags, 'f') != NULL);
lua_Debug ar;
if (!symlnk) {
lua_getstack(L, 1, &ar);
lua_getinfo(L, "Sl", &ar);
const char* s = "Currently only supports symlinks.";
printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n",
ar.short_src, ar.currentline, s, __path_file__, __LINE__);
lua_pushboolean(L, false);
return 1;
}
bool ret = true;
if (symlink(src, link) != 0) {
if (force && (errno == EEXIST)) {
if (unlink(link) == 0) {
if (symlink(src, link) == 0) {
lua_pushboolean(L, ret);
return 1;
}
}
}
ret = false;
lua_getstack(L, 1, &ar);
lua_getinfo(L, "Sl", &ar);
const char* s = strerror(errno);
printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n",
ar.short_src, ar.currentline, s, __path_file__, __LINE__);
}
lua_pushboolean(L, ret);
return 1;
}
int CLuaInstFileHelpers::FileHelpersExist(lua_State *L)
{
CLuaFileHelpers *D = FileHelpersCheckData(L, 1);
if (!D) return 0;
int numargs = lua_gettop(L) - 1;
int min_numargs = 2;
if (numargs < min_numargs) {
printf("luascript exist: not enough arguments (%d, expected %d)\n", numargs, min_numargs);
lua_pushnil(L);
return 1;
}
bool ret = false;
bool err = false;
int errLine = 0;
std::string errMsg = "";
const char *file = "";
file = luaL_checkstring(L, 2);
const char *flag = "";
flag = luaL_checkstring(L, 3);
if (file_exists(file)) {
struct stat FileInfo;
if (lstat(file, &FileInfo) == -1) {
err = true;
errLine = __LINE__;
errMsg = (std::string)strerror(errno);
}
else if (strchr(flag, 'f') != NULL) {
if (S_ISREG(FileInfo.st_mode))
ret = true;
}
else if (strchr(flag, 'l') != NULL) {
if (S_ISLNK(FileInfo.st_mode))
ret = true;
}
else if (strchr(flag, 'd') != NULL) {
if (S_ISDIR(FileInfo.st_mode))
ret = true;
}
else {
err = true;
errLine = __LINE__;
errMsg = (strlen(flag) == 0) ? "no" : "unknown";
errMsg += " flag given.";
}
}
if (err) {
lua_Debug ar;
lua_getstack(L, 1, &ar);
lua_getinfo(L, "Sl", &ar);
printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n",
ar.short_src, ar.currentline, errMsg.c_str(), __path_file__, errLine);
lua_pushnil(L);
return 1;
}
lua_pushboolean(L, ret);
return 1;
}
int CLuaInstFileHelpers::FileHelpersDelete(lua_State *L)
{
CLuaFileHelpers *D = FileHelpersCheckData(L, 1);
if (!D) return 0;
delete D;
return 0;
}