]> granicus.if.org Git - p11-kit/commitdiff
Add compatibility fdwalk() function
authorStef Walter <stefw@gnome.org>
Wed, 20 Feb 2013 10:50:25 +0000 (11:50 +0100)
committerStef Walter <stef@thewalter.net>
Tue, 8 Jul 2014 06:57:30 +0000 (08:57 +0200)
This is used when execing another process to close all open
file descriptors that we don't wish to be inherited.

common/compat.c
common/compat.h
configure.ac

index fef618b42f0c6c5899ac6b93b2521e0ca196a8cf..9314d20b356da606ea57c9361a4aaaf5232bd0b4 100644 (file)
@@ -37,6 +37,7 @@
 #include "compat.h"
 
 #include <assert.h>
+#include <dirent.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
@@ -81,6 +82,8 @@
 
 #ifdef OS_UNIX
 
+#include <unistd.h>
+
 #if defined (HAVE_PROGRAM_INVOCATION_SHORT_NAME) && !HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
 extern char *program_invocation_short_name;
 #endif
@@ -866,3 +869,73 @@ strerror_r (int errnum,
 }
 
 #endif /* HAVE_STRERROR_R */
+
+#ifdef OS_UNIX
+
+#include <unistd.h>
+
+#ifndef HAVE_FDWALK
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+int
+fdwalk (int (* cb) (void *data, int fd),
+        void *data)
+{
+       struct dirent *de;
+       char *end;
+       DIR *dir;
+       int open_max;
+       long num;
+       int res = 0;
+       int fd;
+
+#ifdef HAVE_SYS_RESOURCE_H
+       struct rlimit rl;
+#endif
+
+       dir = opendir ("/proc/self/fd");
+       if (dir != NULL) {
+               while ((de = readdir (dir)) != NULL) {
+                       end = NULL;
+                       num = (int) strtol (de->d_name, &end, 10);
+
+                       /* didn't parse or is the opendir() fd */
+                       if (!end || *end != '\0' ||
+                           (int)num == dirfd (dir))
+                               continue;
+
+                       fd = num;
+
+                       /* call the callback */
+                       res = cb (data, fd);
+                       if (res != 0)
+                               break;
+               }
+
+               closedir (dir);
+               return res;
+       }
+
+       /* No /proc, brute force */
+#ifdef HAVE_SYS_RESOURCE_H
+       if (getrlimit (RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY)
+               open_max = rl.rlim_max;
+       else
+#endif
+               open_max = sysconf (_SC_OPEN_MAX);
+
+       for (fd = 0; fd < open_max; fd++) {
+               res = cb (data, fd);
+               if (res != 0)
+                       break;
+       }
+
+       return res;
+}
+
+#endif /* HAVE_FDWALK */
+
+#endif /* OS_UNIX */
index d7fe414a46bf0c49c677d8c97750df62db0f7059..477137072e899a43a0b3ed9c7e66de051d871837 100644 (file)
@@ -325,4 +325,11 @@ int         strerror_r      (int errnum,
 
 #endif /* HAVE_STRERROR_R */
 
+#ifndef HAVE_FDWALK
+
+int        fdwalk           (int (* cb) (void *data, int fd),
+                             void *data);
+
+#endif
+
 #endif /* __COMPAT_H__ */
index c0e0c5086255d544365cb0252292da86785c6214..e7b24d7b0ed11369b365c450c5adae4777c91a08 100644 (file)
@@ -85,11 +85,14 @@ if test "$os_unix" = "yes"; then
        ])
 
        # These are thngs we can work around
+       AC_CHECK_HEADERS([sys/resource.h])
+       AC_CHECK_MEMBERS([struct dirent.d_type],,,[#include <dirent.h>])
        AC_CHECK_FUNCS([getprogname getexecname basename mkstemp mkdtemp])
        AC_CHECK_FUNCS([getauxval issetugid getresuid])
        AC_CHECK_FUNCS([strnstr memdup strndup strerror_r])
        AC_CHECK_FUNCS([asprintf vasprintf vsnprintf])
        AC_CHECK_FUNCS([timegm])
+       AC_CHECK_FUNCS([fdwalk])
 
        AC_CHECK_DECLS([asprintf, vasprintf], [], [], [[#include <stdio.h>]])