#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #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; }