Changeset

13574:f29d15aef6f8

util.pposix: Add fdopen() to return a Lua file object from an fd Now we can, for example, read/write pipes using Lua's standard I/O routines.
author Matthew Wild <mwild1@gmail.com>
date Wed, 20 Nov 2024 12:08:59 +0000
parents 13573:9277fc78fe39
children 13575:750ff9f579e2
files util-src/pposix.c
diffstat 1 files changed, 32 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/util-src/pposix.c	Tue Nov 19 00:57:24 2024 +0100
+++ b/util-src/pposix.c	Wed Nov 20 12:08:59 2024 +0000
@@ -694,6 +694,37 @@
 	return 2;
 }
 
+/* This helper function is adapted from Lua 5.3's liolib.c */
+static int stdio_fclose (lua_State *L) {
+	int res = -1;
+	luaL_Stream *p = ((luaL_Stream *)luaL_checkudata(L, 1, LUA_FILEHANDLE));
+	if (p->f == NULL) {
+		return 0;
+	}
+	res = fclose(p->f);
+	p->f = NULL;
+	return luaL_fileresult(L, (res == 0), NULL);
+}
+
+static int lc_fdopen(lua_State *L) {
+	int fd = luaL_checkinteger(L, 1);
+	const char *mode = luaL_checkstring(L, 2);
+
+	luaL_Stream *file = (luaL_Stream *)lua_newuserdata(L, sizeof(luaL_Stream));
+	file->closef = stdio_fclose;
+	file->f = fdopen(fd, mode);
+
+	if (!file->f) {
+		luaL_pushfail(L);
+		lua_pushstring(L, strerror(errno));
+		return 2;
+	}
+
+	luaL_getmetatable(L, LUA_FILEHANDLE);
+	lua_setmetatable(L, -2);
+	return 1;
+}
+
 static int lc_uname(lua_State *L) {
 	struct utsname uname_info;
 
@@ -911,6 +942,7 @@
 		{ "mkdir", lc_mkdir },
 
 		{ "pipe", lc_pipe },
+		{ "fdopen", lc_fdopen },
 
 		{ "setrlimit", lc_setrlimit },
 		{ "getrlimit", lc_getrlimit },