diff --git a/libexec/flua/modules/lposix.c b/libexec/flua/modules/lposix.c --- a/libexec/flua/modules/lposix.c +++ b/libexec/flua/modules/lposix.c @@ -30,6 +30,8 @@ #include #include +#include +#include #include #include @@ -63,6 +65,62 @@ return 1; } +static int +lua_chown(lua_State *L) +{ + int n; + const char *path; + uid_t owner = (uid_t) -1; + gid_t group = (gid_t) -1; + + n = lua_gettop(L); + luaL_argcheck(L, n > 1, n, + "chown takes at least two arguments"); + path = luaL_checkstring(L, 1); + if (lua_isinteger(L, 2)) + owner = (uid_t) lua_tointeger(L, 2); + else if (lua_isstring(L, 2)) { + struct passwd *p = getpwnam(lua_tostring(L, 2)); + if (p != NULL) + owner = p->pw_uid; + else + return (luaL_argerror(L, 2, + lua_pushfstring(L, "unknown user %s", + lua_tostring(L, 2)))); + } else if (!lua_isnoneornil(L, 2)) { + const char *type = luaL_typename(L, 2); + return (luaL_argerror(L, 2, + lua_pushfstring(L, "integer or string expected, got %s", + type))); + } + + if (lua_isinteger(L, 3)) + group = (gid_t) lua_tointeger(L, 3); + else if (lua_isstring(L, 3)) { + struct group *g = getgrnam(lua_tostring(L, 3)); + if (g != NULL) + group = g->gr_gid; + else + return (luaL_argerror(L, 3, + lua_pushfstring(L, "unknown user %s", + lua_tostring(L, 3)))); + } else if (!lua_isnoneornil(L, 3)) { + const char *type = luaL_typename(L, 3); + return (luaL_argerror(L, 3, + lua_pushfstring(L, "integer or string expected, got %s", + type))); + } + + if (chown(path, owner, group) == -1) { + lua_pushnil(L); + lua_pushstring(L, strerror(errno)); + lua_pushinteger(L, errno); + return (3); + } + lua_pushinteger(L, 0); + return (1); +} + static int lua_getpid(lua_State *L) { @@ -82,6 +140,7 @@ static const struct luaL_Reg unistdlib[] = { REG_SIMPLE(getpid), + REG_SIMPLE(chown), { NULL, NULL }, }; #undef REG_SIMPLE