shithub: lu9-p9

Download patch

ref: aaaf0950ed2342ba80faea7f5941061542070775
parent: 8b4185716fbbb9b83eb2b2041037f389c3de9b7f
author: kvik <kvik@a-b.xyz>
date: Sun Apr 18 18:37:49 EDT 2021

fs: implement file:dup()

--- a/fs.c
+++ b/fs.c
@@ -303,24 +303,45 @@
 }
 
 static int
-p9_remove(lua_State *L)
+p9_iounit(lua_State *L)
 {
-	const char *file;
+	int fd;
 	
-	file = luaL_checkstring(L, 1);
-	if(remove(file) == -1)
-		return error(L, "remove: %r");
-	lua_pushboolean(L, 1);
+	fd = filefd(L, 1);
+	lua_pushinteger(L, iounit(fd));
 	return 1;
 }
 
 static int
-p9_iounit(lua_State *L)
+p9_dup(lua_State *L)
 {
-	int fd;
+	int fd, new, na;
 	
+	na = lua_gettop(L);
 	fd = filefd(L, 1);
-	lua_pushinteger(L, iounit(fd));
+	if(na == 2)
+		new = filefd(L, 2);
+	else
+		new = -1;
+	if((new = dup(fd, new)) == -1)
+		return error(L, "dup: %r");
+	if(na == 2){
+		lua_pushinteger(L, new);
+		lua_setfield(L, 2, "fd");
+		return 1;
+	}
+	return filenew(L, new);
+}
+
+static int
+p9_remove(lua_State *L)
+{
+	const char *file;
+	
+	file = luaL_checkstring(L, 1);
+	if(remove(file) == -1)
+		return error(L, "remove: %r");
+	lua_pushboolean(L, 1);
 	return 1;
 }
 
--- a/p9.c
+++ b/p9.c
@@ -192,6 +192,7 @@
 		{"seek", p9_seek},
 		{"iounit", p9_iounit},
 		{"path", p9_path},
+		{"dup", p9_dup},
 		{nil, nil},
 	};
 	luaL_newmetatable(L, "p9-File");
--- a/test.lua
+++ b/test.lua
@@ -82,6 +82,24 @@
 	f:close()
 end
 
+-- file:dup()
+do
+	local a, b = assert(p9.pipe())
+	local c = assert(a:dup())
+	a:write("hello")
+	assert(b:read() == "hello")
+	c:write("world")
+	assert(b:read() == "world")
+	a:close() b:close() c:close()
+	
+	a = assert(p9.open("/lib/glass"))
+	local buf = a:read()
+	b = assert(p9.open("/lib/bullshit"))
+	b = assert(a:dup(b))
+	b:seek(0)
+	assert(b:read() == buf)
+end
+	
 -- pipe
 do
 	local p₀, p₁ = assert(p9.pipe())