xref: /freebsd/libexec/flua/modules/lposix.c (revision 280f11f1be54370fcc289ee259a1b86637170ea1)
1506f3640SKyle Evans /*-
2506f3640SKyle Evans  * Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org>
3506f3640SKyle Evans  *
4506f3640SKyle Evans  * Redistribution and use in source and binary forms, with or without
5506f3640SKyle Evans  * modification, are permitted provided that the following conditions
6506f3640SKyle Evans  * are met:
7506f3640SKyle Evans  * 1. Redistributions of source code must retain the above copyright
8506f3640SKyle Evans  *    notice, this list of conditions and the following disclaimer.
9506f3640SKyle Evans  * 2. Redistributions in binary form must reproduce the above copyright
10506f3640SKyle Evans  *    notice, this list of conditions and the following disclaimer in the
11506f3640SKyle Evans  *    documentation and/or other materials provided with the distribution.
12506f3640SKyle Evans  *
13506f3640SKyle Evans  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14506f3640SKyle Evans  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15506f3640SKyle Evans  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16506f3640SKyle Evans  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17506f3640SKyle Evans  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18506f3640SKyle Evans  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19506f3640SKyle Evans  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20506f3640SKyle Evans  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21506f3640SKyle Evans  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22506f3640SKyle Evans  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23506f3640SKyle Evans  * SUCH DAMAGE.
24506f3640SKyle Evans  *
25506f3640SKyle Evans  */
26506f3640SKyle Evans 
27506f3640SKyle Evans #include <sys/cdefs.h>
28506f3640SKyle Evans __FBSDID("$FreeBSD$");
29506f3640SKyle Evans 
30405e3338SEd Maste #include <sys/stat.h>
31405e3338SEd Maste 
32405e3338SEd Maste #include <errno.h>
33a1ab15abSBaptiste Daroussin #include <grp.h>
34a1ab15abSBaptiste Daroussin #include <pwd.h>
35405e3338SEd Maste #include <string.h>
36506f3640SKyle Evans #include <unistd.h>
37506f3640SKyle Evans 
38506f3640SKyle Evans #include <lua.h>
39506f3640SKyle Evans #include "lauxlib.h"
40506f3640SKyle Evans #include "lposix.h"
41506f3640SKyle Evans 
42506f3640SKyle Evans /*
43506f3640SKyle Evans  * Minimal implementation of luaposix needed for internal FreeBSD bits.
44506f3640SKyle Evans  */
45506f3640SKyle Evans 
46506f3640SKyle Evans static int
47405e3338SEd Maste lua_chmod(lua_State *L)
48405e3338SEd Maste {
49405e3338SEd Maste 	int n;
50405e3338SEd Maste 	const char *path;
51405e3338SEd Maste 	mode_t mode;
52405e3338SEd Maste 
53405e3338SEd Maste 	n = lua_gettop(L);
54405e3338SEd Maste 	luaL_argcheck(L, n == 2, n > 2 ? 3 : n,
55405e3338SEd Maste 	    "chmod takes exactly two arguments");
56405e3338SEd Maste 	path = luaL_checkstring(L, 1);
57405e3338SEd Maste 	mode = (mode_t)luaL_checkinteger(L, 2);
58405e3338SEd Maste 	if (chmod(path, mode) == -1) {
59405e3338SEd Maste 		lua_pushnil(L);
60405e3338SEd Maste 		lua_pushstring(L, strerror(errno));
61405e3338SEd Maste 		lua_pushinteger(L, errno);
62405e3338SEd Maste 		return 3;
63405e3338SEd Maste 	}
64405e3338SEd Maste 	lua_pushinteger(L, 0);
65405e3338SEd Maste 	return 1;
66405e3338SEd Maste }
67405e3338SEd Maste 
68405e3338SEd Maste static int
69a1ab15abSBaptiste Daroussin lua_chown(lua_State *L)
70a1ab15abSBaptiste Daroussin {
71a1ab15abSBaptiste Daroussin 	int n;
72a1ab15abSBaptiste Daroussin 	const char *path;
73a1ab15abSBaptiste Daroussin 	uid_t owner = (uid_t) -1;
74a1ab15abSBaptiste Daroussin 	gid_t group = (gid_t) -1;
75a1ab15abSBaptiste Daroussin 
76a1ab15abSBaptiste Daroussin 	n = lua_gettop(L);
77a1ab15abSBaptiste Daroussin 	luaL_argcheck(L, n > 1, n,
78a1ab15abSBaptiste Daroussin 	   "chown takes at least two arguments");
79a1ab15abSBaptiste Daroussin 	path = luaL_checkstring(L, 1);
80a1ab15abSBaptiste Daroussin 	if (lua_isinteger(L, 2))
81a1ab15abSBaptiste Daroussin 		owner = (uid_t) lua_tointeger(L, 2);
82a1ab15abSBaptiste Daroussin 	else if (lua_isstring(L, 2)) {
83a1ab15abSBaptiste Daroussin 		struct passwd *p = getpwnam(lua_tostring(L, 2));
84a1ab15abSBaptiste Daroussin 		if (p != NULL)
85a1ab15abSBaptiste Daroussin 			owner = p->pw_uid;
86a1ab15abSBaptiste Daroussin 		else
87a1ab15abSBaptiste Daroussin 			return (luaL_argerror(L, 2,
88a1ab15abSBaptiste Daroussin 			    lua_pushfstring(L, "unknown user %s",
89a1ab15abSBaptiste Daroussin 			    lua_tostring(L, 2))));
90a1ab15abSBaptiste Daroussin 	} else if (!lua_isnoneornil(L, 2)) {
91a1ab15abSBaptiste Daroussin 		const char *type = luaL_typename(L, 2);
92a1ab15abSBaptiste Daroussin 		return (luaL_argerror(L, 2,
93a1ab15abSBaptiste Daroussin 		    lua_pushfstring(L, "integer or string expected, got %s",
94a1ab15abSBaptiste Daroussin 		    type)));
95a1ab15abSBaptiste Daroussin 	}
96a1ab15abSBaptiste Daroussin 
97a1ab15abSBaptiste Daroussin 	if (lua_isinteger(L, 3))
98a1ab15abSBaptiste Daroussin 		group = (gid_t) lua_tointeger(L, 3);
99a1ab15abSBaptiste Daroussin 	else if (lua_isstring(L, 3)) {
100a1ab15abSBaptiste Daroussin 		struct group *g = getgrnam(lua_tostring(L, 3));
101a1ab15abSBaptiste Daroussin 		if (g != NULL)
102a1ab15abSBaptiste Daroussin 			group = g->gr_gid;
103a1ab15abSBaptiste Daroussin 		else
104a1ab15abSBaptiste Daroussin 			return (luaL_argerror(L, 3,
105*280f11f1SBaptiste Daroussin 			    lua_pushfstring(L, "unknown group %s",
106a1ab15abSBaptiste Daroussin 			    lua_tostring(L, 3))));
107a1ab15abSBaptiste Daroussin 	} else if (!lua_isnoneornil(L, 3)) {
108a1ab15abSBaptiste Daroussin 		const char *type = luaL_typename(L, 3);
109a1ab15abSBaptiste Daroussin 		return (luaL_argerror(L, 3,
110a1ab15abSBaptiste Daroussin 		    lua_pushfstring(L, "integer or string expected, got %s",
111a1ab15abSBaptiste Daroussin 		    type)));
112a1ab15abSBaptiste Daroussin 	}
113a1ab15abSBaptiste Daroussin 
114a1ab15abSBaptiste Daroussin 	if (chown(path, owner, group) == -1) {
115a1ab15abSBaptiste Daroussin 		lua_pushnil(L);
116a1ab15abSBaptiste Daroussin 		lua_pushstring(L, strerror(errno));
117a1ab15abSBaptiste Daroussin 		lua_pushinteger(L, errno);
118a1ab15abSBaptiste Daroussin 		return (3);
119a1ab15abSBaptiste Daroussin 	}
120a1ab15abSBaptiste Daroussin 	lua_pushinteger(L, 0);
121a1ab15abSBaptiste Daroussin 	return (1);
122a1ab15abSBaptiste Daroussin }
123a1ab15abSBaptiste Daroussin 
124a1ab15abSBaptiste Daroussin static int
125506f3640SKyle Evans lua_getpid(lua_State *L)
126506f3640SKyle Evans {
127506f3640SKyle Evans 	int n;
128506f3640SKyle Evans 
129506f3640SKyle Evans 	n = lua_gettop(L);
130506f3640SKyle Evans 	luaL_argcheck(L, n == 0, 1, "too many arguments");
131506f3640SKyle Evans 	lua_pushinteger(L, getpid());
132506f3640SKyle Evans 	return 1;
133506f3640SKyle Evans }
134506f3640SKyle Evans 
135506f3640SKyle Evans #define REG_SIMPLE(n)	{ #n, lua_ ## n }
136405e3338SEd Maste static const struct luaL_Reg sys_statlib[] = {
137405e3338SEd Maste 	REG_SIMPLE(chmod),
138405e3338SEd Maste 	{ NULL, NULL },
139405e3338SEd Maste };
140405e3338SEd Maste 
141506f3640SKyle Evans static const struct luaL_Reg unistdlib[] = {
142506f3640SKyle Evans 	REG_SIMPLE(getpid),
143a1ab15abSBaptiste Daroussin 	REG_SIMPLE(chown),
144506f3640SKyle Evans 	{ NULL, NULL },
145506f3640SKyle Evans };
146506f3640SKyle Evans #undef REG_SIMPLE
147506f3640SKyle Evans 
148506f3640SKyle Evans int
149405e3338SEd Maste luaopen_posix_sys_stat(lua_State *L)
150405e3338SEd Maste {
151405e3338SEd Maste 	luaL_newlib(L, sys_statlib);
152405e3338SEd Maste 	return 1;
153405e3338SEd Maste }
154405e3338SEd Maste 
155405e3338SEd Maste int
156506f3640SKyle Evans luaopen_posix_unistd(lua_State *L)
157506f3640SKyle Evans {
158506f3640SKyle Evans 	luaL_newlib(L, unistdlib);
159506f3640SKyle Evans 	return 1;
160506f3640SKyle Evans }
161