11 changed files with 318 additions and 23 deletions
@ -0,0 +1,232 @@
|
||||
|
||||
#include <lighttpd/core_lua.h> |
||||
|
||||
#include <lualib.h> |
||||
#include <lauxlib.h> |
||||
|
||||
|
||||
/* struct stat */ |
||||
#define LUA_STAT "struct stat" |
||||
|
||||
struct stat* li_lua_get_stat(lua_State *L, int ndx) { |
||||
if (!lua_isuserdata(L, ndx)) return NULL; |
||||
if (!lua_getmetatable(L, ndx)) return NULL; |
||||
luaL_getmetatable(L, LUA_STAT); |
||||
if (lua_isnil(L, -1) || lua_isnil(L, -2) || !lua_equal(L, -1, -2)) { |
||||
lua_pop(L, 2); |
||||
return NULL; |
||||
} |
||||
lua_pop(L, 2); |
||||
return (struct stat*) lua_touserdata(L, ndx); |
||||
} |
||||
|
||||
typedef int (*lua_stat_Attrib)(struct stat *st, lua_State *L); |
||||
|
||||
static int lua_stat_attr_read_is_file(struct stat *st, lua_State *L) { |
||||
lua_pushboolean(L, S_ISREG(st->st_mode)); |
||||
return 1; |
||||
} |
||||
|
||||
static int lua_stat_attr_read_is_dir(struct stat *st, lua_State *L) { |
||||
lua_pushboolean(L, S_ISREG(st->st_mode)); |
||||
return 1; |
||||
} |
||||
|
||||
static int lua_stat_attr_read_is_char(struct stat *st, lua_State *L) { |
||||
lua_pushboolean(L, S_ISCHR(st->st_mode)); |
||||
return 1; |
||||
} |
||||
|
||||
static int lua_stat_attr_read_is_block(struct stat *st, lua_State *L) { |
||||
lua_pushboolean(L, S_ISBLK(st->st_mode)); |
||||
return 1; |
||||
} |
||||
|
||||
static int lua_stat_attr_read_is_socket(struct stat *st, lua_State *L) { |
||||
lua_pushboolean(L, S_ISSOCK(st->st_mode)); |
||||
return 1; |
||||
} |
||||
|
||||
static int lua_stat_attr_read_is_link(struct stat *st, lua_State *L) { |
||||
lua_pushboolean(L, S_ISLNK(st->st_mode)); |
||||
return 1; |
||||
} |
||||
|
||||
static int lua_stat_attr_read_is_fifo(struct stat *st, lua_State *L) { |
||||
lua_pushboolean(L, S_ISFIFO(st->st_mode)); |
||||
return 1; |
||||
} |
||||
|
||||
static int lua_stat_attr_read_mode(struct stat *st, lua_State *L) { |
||||
lua_pushinteger(L, st->st_mode); |
||||
return 1; |
||||
} |
||||
|
||||
static int lua_stat_attr_read_mtime(struct stat *st, lua_State *L) { |
||||
lua_pushinteger(L, st->st_mtime); |
||||
return 1; |
||||
} |
||||
|
||||
static int lua_stat_attr_read_ctime(struct stat *st, lua_State *L) { |
||||
lua_pushinteger(L, st->st_ctime); |
||||
return 1; |
||||
} |
||||
|
||||
static int lua_stat_attr_read_atime(struct stat *st, lua_State *L) { |
||||
lua_pushinteger(L, st->st_atime); |
||||
return 1; |
||||
} |
||||
|
||||
static int lua_stat_attr_read_uid(struct stat *st, lua_State *L) { |
||||
lua_pushinteger(L, st->st_uid); |
||||
return 1; |
||||
} |
||||
|
||||
static int lua_stat_attr_read_gid(struct stat *st, lua_State *L) { |
||||
lua_pushinteger(L, st->st_gid); |
||||
return 1; |
||||
} |
||||
|
||||
static int lua_stat_attr_read_size(struct stat *st, lua_State *L) { |
||||
lua_pushinteger(L, st->st_size); |
||||
return 1; |
||||
} |
||||
|
||||
static int lua_stat_attr_read_ino(struct stat *st, lua_State *L) { |
||||
lua_pushinteger(L, st->st_ino); |
||||
return 1; |
||||
} |
||||
|
||||
static int lua_stat_attr_read_dev(struct stat *st, lua_State *L) { |
||||
lua_pushinteger(L, st->st_dev); |
||||
return 1; |
||||
} |
||||
|
||||
#define AR(m) { #m, lua_stat_attr_read_##m, NULL } |
||||
#define AW(m) { #m, NULL, lua_stat_attr_write_##m } |
||||
#define ARW(m) { #m, lua_stat_attr_read_##m, lua_stat_attr_write_##m } |
||||
|
||||
static const struct { |
||||
const char* key; |
||||
lua_stat_Attrib read_attr, write_attr; |
||||
} stat_attribs[] = { |
||||
AR(is_file), |
||||
AR(is_dir), |
||||
AR(is_char), |
||||
AR(is_block), |
||||
AR(is_socket), |
||||
AR(is_link), |
||||
AR(is_fifo), |
||||
AR(mode), |
||||
AR(mtime), |
||||
{ "ctime", lua_stat_attr_read_ctime, NULL }, /* avoid poisoned ctime */ |
||||
AR(atime), |
||||
AR(uid), |
||||
AR(gid), |
||||
AR(size), |
||||
AR(ino), |
||||
AR(dev), |
||||
|
||||
{ NULL, NULL, NULL } |
||||
}; |
||||
|
||||
static int lua_stat_index(lua_State *L) { |
||||
struct stat *st; |
||||
const char *key; |
||||
int i; |
||||
|
||||
if (lua_gettop(L) != 2) { |
||||
lua_pushstring(L, "incorrect number of arguments"); |
||||
lua_error(L); |
||||
} |
||||
|
||||
if (li_lua_metatable_index(L)) return 1; |
||||
|
||||
st = li_lua_get_stat(L, 1); |
||||
if (!st) return 0; |
||||
|
||||
if (lua_isnumber(L, 2)) return 0; |
||||
if (!lua_isstring(L, 2)) return 0; |
||||
|
||||
key = lua_tostring(L, 2); |
||||
for (i = 0; stat_attribs[i].key ; i++) { |
||||
if (0 == strcmp(key, stat_attribs[i].key)) { |
||||
if (stat_attribs[i].read_attr) |
||||
return stat_attribs[i].read_attr(st, L); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
lua_pushstring(L, "cannot read attribute "); |
||||
lua_pushstring(L, key); |
||||
lua_pushstring(L, " in struct stat"); |
||||
lua_concat(L, 3); |
||||
lua_error(L); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int lua_stat_newindex(lua_State *L) { |
||||
struct stat *st; |
||||
const char *key; |
||||
int i; |
||||
|
||||
if (lua_gettop(L) != 3) { |
||||
lua_pushstring(L, "incorrect number of arguments"); |
||||
lua_error(L); |
||||
} |
||||
|
||||
st = li_lua_get_stat(L, 1); |
||||
if (!st) return 0; |
||||
|
||||
if (lua_isnumber(L, 2)) return 0; |
||||
if (!lua_isstring(L, 2)) return 0; |
||||
|
||||
key = lua_tostring(L, 2); |
||||
for (i = 0; stat_attribs[i].key ; i++) { |
||||
if (0 == strcmp(key, stat_attribs[i].key)) { |
||||
if (stat_attribs[i].write_attr) |
||||
return stat_attribs[i].write_attr(st, L); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
lua_pushstring(L, "cannot write attribute "); |
||||
lua_pushstring(L, key); |
||||
lua_pushstring(L, "in struct stat"); |
||||
lua_concat(L, 3); |
||||
lua_error(L); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static const luaL_Reg stat_mt[] = { |
||||
{ "__index", lua_stat_index }, |
||||
{ "__newindex", lua_stat_newindex }, |
||||
{ NULL, NULL } |
||||
}; |
||||
|
||||
static void init_stat_mt(lua_State *L) { |
||||
luaL_register(L, NULL, stat_mt); |
||||
} |
||||
|
||||
void li_lua_init_stat_mt(lua_State *L) { |
||||
if (luaL_newmetatable(L, LUA_STAT)) { |
||||
init_stat_mt(L); |
||||
} |
||||
lua_pop(L, 1); |
||||
} |
||||
|
||||
int li_lua_push_stat(lua_State *L, struct stat *st) { |
||||
struct stat *pst; |
||||
|
||||
pst = (struct stat*) lua_newuserdata(L, sizeof(struct stat)); |
||||
*pst = *st; |
||||
|
||||
if (luaL_newmetatable(L, LUA_STAT)) { |
||||
init_stat_mt(L); |
||||
} |
||||
|
||||
lua_setmetatable(L, -2); |
||||
return 1; |
||||
} |
Loading…
Reference in new issue