git: a1ab15abe2e2 - main - flua: add a chown(2) binding

From: Baptiste Daroussin <bapt_at_FreeBSD.org>
Date: Fri, 25 Nov 2022 07:50:47 UTC
The branch main has been updated by bapt:

URL: https://cgit.FreeBSD.org/src/commit/?id=a1ab15abe2e2a1ed92cbad056df71afff7e8794e

commit a1ab15abe2e2a1ed92cbad056df71afff7e8794e
Author:     Baptiste Daroussin <bapt@FreeBSD.org>
AuthorDate: 2022-11-24 08:16:05 +0000
Commit:     Baptiste Daroussin <bapt@FreeBSD.org>
CommitDate: 2022-11-25 07:49:58 +0000

    flua: add a chown(2) binding
    
    The main difference with the chown in luaposix, is that it checks
    and reports if a user or a group do exist when a string is passed
    as arguments
    
    Reviewed by:    kevans
    Differential Revision:  https://reviews.freebsd.org/D37479
---
 libexec/flua/modules/lposix.c | 59 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/libexec/flua/modules/lposix.c b/libexec/flua/modules/lposix.c
index adf3a7bb9a1f..88687be2788c 100644
--- a/libexec/flua/modules/lposix.c
+++ b/libexec/flua/modules/lposix.c
@@ -30,6 +30,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/stat.h>
 
 #include <errno.h>
+#include <grp.h>
+#include <pwd.h>
 #include <string.h>
 #include <unistd.h>
 
@@ -63,6 +65,62 @@ lua_chmod(lua_State *L)
 	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 sys_statlib[] = {
 
 static const struct luaL_Reg unistdlib[] = {
 	REG_SIMPLE(getpid),
+	REG_SIMPLE(chown),
 	{ NULL, NULL },
 };
 #undef REG_SIMPLE