]> git.e2factory.org Git - e2factory.git/commitdiff
e2util: implement closefrom()
authorTobias Ulmer <tu@emlix.com>
Wed, 7 Oct 2015 16:21:05 +0000 (18:21 +0200)
committerTobias Ulmer <tu@emlix.com>
Thu, 8 Oct 2015 15:49:17 +0000 (17:49 +0200)
Signed-off-by: Tobias Ulmer <tu@emlix.com>
generic/e2util.c

index dc38f90e829b5b8e7e5190c75128107b8c5c61ac..651cd8a69b1623a49c3a621071320f2afa24d326 100644 (file)
@@ -772,6 +772,58 @@ signal_reset(lua_State *L)
        return 1;
 }
 
+
+/*
+ * e2util.closefrom() closes all file descriptors >= * fd_from.
+ * closefrom() is commonly available on the BSDs, but on Linux we
+ * have to use this crutch (which fails when /proc is not mounted).
+ *
+ * Lua:
+ * e2util.closefrom(number) returns true OR false and an errno string.
+ * May throw an exception.
+ */
+static int
+closefrom(lua_State *L)
+{
+       DIR *d = NULL;
+       int myself, from, eno = 0;
+       struct dirent *de;
+
+       from = luaL_checkinteger(L, 1);
+
+       d = opendir("/proc/self/fd");
+       if (!d)
+               goto error;
+       /* make sure we don't close our directory fd yet */
+       myself = dirfd(d);
+       if (myself < 0)
+               goto error;
+
+       while ((de = readdir(d)) != NULL) {
+               int fd;
+
+               if (de->d_name[0] < '0' || de->d_name[0] > '9')
+                       continue;
+
+               fd = atoi(de->d_name);
+               if (fd < from || fd == myself)
+                       continue;
+
+               close(fd);
+       }
+
+       closedir(d);
+       lua_pushboolean(L, 1);
+       return 1;
+error:
+       eno = errno;
+       if (d)
+               closedir(d);
+       lua_pushboolean(L, 0);
+       lua_pushstring(L, strerror(eno));
+       return 2;
+}
+
 /* e2util.catch_interrupt()
 
    Establish signal handler for SIGINT that aborts. */
@@ -832,6 +884,7 @@ static luaL_Reg lib[] = {
        { "exec", do_exec },
        { "getpid", do_getpid },
        { "signal_reset", signal_reset },
+       { "closefrom", closefrom },
        { NULL, NULL }
 };