126 lines
2.5 KiB
C
126 lines
2.5 KiB
C
#define _GNU_SOURCE
|
|
|
|
#include <lua.h>
|
|
#include <lualib.h>
|
|
#include <lauxlib.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <err.h>
|
|
|
|
#include "lib.h"
|
|
|
|
static const char *fs_check_path(lua_State *ctx, int i, size_t *psize) {
|
|
size_t n;
|
|
const char *path = luaL_checklstring(ctx, 1, &n);
|
|
|
|
size_t real_len = strlen(path);
|
|
if (n != real_len) {
|
|
luaL_error(ctx, "path may not contain \\0");
|
|
return NULL;
|
|
}
|
|
|
|
if (psize) *psize = n;
|
|
|
|
return path;
|
|
}
|
|
|
|
static int lib_fs_mkdir(lua_State *ctx) {
|
|
size_t path_size;
|
|
const char *ro_path = fs_check_path(ctx, 1, &path_size);
|
|
bool recursive = lua_toboolean(ctx, 2);
|
|
|
|
if (recursive) {
|
|
char path[path_size + 1];
|
|
memcpy(path, ro_path, path_size + 1);
|
|
|
|
for (size_t i = 0; i <= path_size ; i++) {
|
|
if (path[i] == '/' || path[i] == '\0') {
|
|
path[i] = '\0';
|
|
|
|
if (mkdir(path, 0755) < 0 && errno != EEXIST) {
|
|
lua_pushnil(ctx);
|
|
lua_pushfstring(ctx, "can't make directory: %s", strerror(errno));
|
|
return 12;
|
|
}
|
|
|
|
if (i < path_size) path[i] = '/';
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (mkdir(ro_path, 0755) < 0) {
|
|
lua_pushnil(ctx);
|
|
lua_pushfstring(ctx, "can't make directory: %s", strerror(errno));
|
|
return 12;
|
|
}
|
|
}
|
|
|
|
lua_pushboolean(ctx, true);
|
|
return 1;
|
|
}
|
|
static int lib_fs_symlink(lua_State *ctx) {
|
|
const char *src = fs_check_path(ctx, 1, NULL);
|
|
const char *dst = fs_check_path(ctx, 2, NULL);
|
|
|
|
if (symlink(src, dst) < 0) {
|
|
lua_pushnil(ctx);
|
|
lua_pushfstring(ctx, "failed to chmod: %s", strerror(errno));
|
|
return 2;
|
|
}
|
|
|
|
lua_pushboolean(ctx, true);
|
|
return 1;
|
|
}
|
|
static int lib_fs_chmod(lua_State *ctx) {
|
|
const char *path = fs_check_path(ctx, 1, NULL);
|
|
int mode;
|
|
|
|
if (lua_isinteger(ctx, 2)) {
|
|
mode = lua_tointeger(ctx, 2);
|
|
mode = mode & 0xFFF;
|
|
}
|
|
else {
|
|
const char *strmode = luaL_checkstring(ctx, 2);
|
|
|
|
mode = 0;
|
|
|
|
for (size_t i = 0; strmode[i]; i++) {
|
|
char c = strmode[i];
|
|
if (c >= '0' && c <= '7') {
|
|
mode <<= 3;
|
|
mode |= c - '0';
|
|
}
|
|
else {
|
|
return luaL_error(ctx, "invalid mode '%s' - must be an octal integer", strmode);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (chmod(path, mode) < 0) {
|
|
lua_pushnil(ctx);
|
|
lua_pushfstring(ctx, "failed to chmod: %s", strerror(errno));
|
|
return 2;
|
|
}
|
|
|
|
lua_pushboolean(ctx, true);
|
|
return 1;
|
|
}
|
|
|
|
int fs_open_lib(lua_State *ctx) {
|
|
luaL_newlib(ctx, ((luaL_Reg[]) {
|
|
{ "mkdir", lib_fs_mkdir },
|
|
{ "chmod", lib_fs_chmod },
|
|
{ "symlink", lib_fs_symlink },
|
|
{ NULL, NULL },
|
|
}));
|
|
|
|
return 1;
|
|
}
|