From 1d596b23fb1be9d15e0875d2f550a9e5a816cda9 Mon Sep 17 00:00:00 2001 From: Tobias Ulmer Date: Wed, 7 Oct 2015 18:37:42 +0200 Subject: [PATCH] luafile: new function cloexec() to set FD_CLOEXEC on file Signed-off-by: Tobias Ulmer --- generic/luafile.lua | 16 ++++++++++++++++ generic/luafile_ll.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/generic/luafile.lua b/generic/luafile.lua index b79c678..cadb354 100644 --- a/generic/luafile.lua +++ b/generic/luafile.lua @@ -141,6 +141,22 @@ function luafile.dup2(oldfd, newfd) return nil end + +--- Set the CLOEXEC flag on underlying file descriptor. Throws exception on +-- invalid input. +-- @param something can be a file descriptor number, luafile object, or io file +-- @param set True to set the CLOEXEC, False to unset it. Defaults to True. +-- @return True on success, False on error. +function luafile.cloexec(something, set) + assert(something ~= nil) + assert(set == nil or type(set) == "boolean") + if set == nil then + set = true + end + + return luafile_ll.cloexec(something, set) +end + return strict.lock(luafile) -- vim:sw=4:sts=4:et: diff --git a/generic/luafile_ll.c b/generic/luafile_ll.c index 121bf8b..b3c6994 100644 --- a/generic/luafile_ll.c +++ b/generic/luafile_ll.c @@ -250,6 +250,50 @@ lua_dup2(lua_State *lua) return 1; } +static int +lua_cloexec(lua_State *lua) +{ + int fd = -1, rc, cloexec; + FILE *f = NULL; + + if (lua_isnumber(lua, 1)) { + fd = luaL_checkint(lua, 1); + } else if (lua_istable(lua, 1)) { + lua_pushstring(lua, "file"); // key + lua_gettable(lua, 1); + if (!lua_islightuserdata(lua, -1)) + luaL_argerror(lua, 1, "not a luafile table"); + f = (FILE *)lua_topointer(lua, -1); + } else if (lua_isuserdata(lua, 1)) { + FILE **p; + p = (FILE **)luaL_checkudata(lua, 1, LUA_FILEHANDLE); + if (*p == NULL) { + lua_pushfstring(lua, "%s: closed lua filehandle", + __func__); + lua_error(lua); + } + f = *p; + } + + if (f) { + fd = fileno(f); + } + + if (fd < 0) { + luaL_argerror(lua, 1, "fd/luafile/io file required"); + } + + if (lua_isboolean(lua, 2)) { + cloexec = lua_toboolean(lua, 2); + } else { + luaL_argerror(lua, 2, "boolean required"); + } + + rc = fcntl(fd, F_SETFD, cloexec ? FD_CLOEXEC : 0); + lua_pushboolean(lua, (rc == 0)); + return 1; +} + static luaL_Reg lib[] = { { "fopen", lua_fopen }, { "fdopen", lua_fdopen }, @@ -264,6 +308,7 @@ static luaL_Reg lib[] = { { "setlinebuf", lua_setlinebuf }, { "pipe", lua_pipe }, { "dup2", lua_dup2 }, + { "cloexec", lua_cloexec }, { NULL, NULL } }; -- 2.39.5