raster pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=1127409564ed41ac1d0f9494b15abc9ba1280449

commit 1127409564ed41ac1d0f9494b15abc9ba1280449
Author: Carsten Haitzler (Rasterman) <[email protected]>
Date:   Wed Nov 20 08:43:26 2019 +0000

    eina - add portable close all fd's we don't need function
    
    close all fd's starting at a given fd and then leving out an exception
    list specially passed, if any. useful for fork+exec. this uses it in
    efl's fork+exec paths.
    
    @feat
---
 src/lib/ecore/ecore_exe_posix.c |  4 ++
 src/lib/ecore/efl_exe.c         |  5 +++
 src/lib/eina/eina_file.c        | 84 +++++++++++++++++++++++++++++++++++++++++
 src/lib/eina/eina_file.h        | 17 +++++++++
 4 files changed, 110 insertions(+)

diff --git a/src/lib/ecore/ecore_exe_posix.c b/src/lib/ecore/ecore_exe_posix.c
index 6a0cc3b79e..4a9b7a3338 100644
--- a/src/lib/ecore/ecore_exe_posix.c
+++ b/src/lib/ecore/ecore_exe_posix.c
@@ -364,6 +364,10 @@ _impl_ecore_exe_efl_object_finalize(Eo *obj, 
Ecore_Exe_Data *exe)
              E_NO_ERRNO(result, close(statusPipe[0]), ok);
              E_IF_NO_ERRNO(result, eina_file_close_on_exec(statusPipe[1], 
EINA_TRUE), ok) /* close on exec shows success */
              {
+                int except[2] = { 0, -1 };
+
+                except[0] = statusPipe[1];
+                eina_file_close_from(3, except);
                 /* Run the actual command. */
                  _ecore_exe_exec_it(exe_cmd, flags); /* no return */
              }
diff --git a/src/lib/ecore/efl_exe.c b/src/lib/ecore/efl_exe.c
index f6ae3bfdde..8609dbfac5 100644
--- a/src/lib/ecore/efl_exe.c
+++ b/src/lib/ecore/efl_exe.c
@@ -540,6 +540,11 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
        pd->env = NULL;
      }
 
+   // close all fd's other than the first 3 (0, 1, 2) and exited write fd
+   int except[2] = { 0, -1 };
+   except[0] = pd->fd.exited_write;
+   eina_file_close_from(3, except);
+
    // actually execute!
    _exec(cmd, pd->flags, td->flags);
    // we couldn't exec... uh oh. HAAAAAAAALP!
diff --git a/src/lib/eina/eina_file.c b/src/lib/eina/eina_file.c
index f4d0e7221c..6277ad6a3e 100644
--- a/src/lib/eina/eina_file.c
+++ b/src/lib/eina/eina_file.c
@@ -36,6 +36,10 @@
 #endif
 #include <fcntl.h>
 
+#ifdef HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
+#endif
+
 #define PATH_DELIM '/'
 
 #include "eina_config.h"
@@ -1252,3 +1256,83 @@ eina_file_statat(void *container, Eina_File_Direct_Info 
*info, Eina_Stat *st)
    return 0;
 }
 
+EAPI void
+eina_file_close_from(int fd, int *except_fd)
+{
+#if defined(_WIN32)
+   // XXX: what do to here? anything?
+#else
+#ifdef HAVE_DIRENT_H
+   DIR *dir;
+
+   dir = opendir("/proc/sefl/fd");
+   if (!dir) dir = opendir("/dev/fd");
+   if (dir)
+     {
+        struct dirent *dp;
+        const char *fname;
+        int *closes = NULL;
+        int num_closes = 0, i;
+
+        for (;;)
+          {
+skip:
+             dp = readdir(dir);
+             if (!dp) break;
+             fname = dp->d_name;
+
+             if ((fname[0] >= '0') && (fname[0] <= '9'))
+               {
+                  int num = atoi(fname);
+                  if (num >= fd)
+                    {
+                       if (except_fd)
+                         {
+                            int j;
+
+                            for (j = 0; except_fd[j] >= 0; j++)
+                              {
+                                 if (except_fd[j] == num) goto skip;
+                              }
+                         }
+                       num_closes++;
+                       int *tmp = realloc(closes, num_closes * sizeof(int));
+                       if (!tmp) num_closes--;
+                       else
+                         {
+                            closes = tmp;
+                            closes[num_closes - 1] = num;
+                         }
+                    }
+               }
+          }
+        closedir(dir);
+        for (i = 0; i < num_closes; i++) close(closes[i]);
+        free(closes);
+        return;
+     }
+#endif
+   int i, max = 1024;
+
+# ifdef HAVE_SYS_RESOURCE_H
+   struct rlimit lim;
+   if (getrlimit(RLIMIT_NOFILE, &lim) < 0) return;
+   max = lim.rlim_max;
+# endif
+   for (i = fd; i < max;)
+     {
+        if (except_fd)
+          {
+             int j;
+
+             for (j = 0; except_fd[j] >= 0; j++)
+               {
+                  if (except_fd[j] == i) goto skip2;
+               }
+          }
+        close(i);
+skip2:
+        i++;
+     }
+#endif
+}
diff --git a/src/lib/eina/eina_file.h b/src/lib/eina/eina_file.h
index ade3b4fd79..404dea1ccb 100644
--- a/src/lib/eina/eina_file.h
+++ b/src/lib/eina/eina_file.h
@@ -347,6 +347,23 @@ EAPI Eina_Iterator *eina_file_stat_ls(const char *dir) 
EINA_WARN_UNUSED_RESULT E
  */
 EAPI int eina_file_statat(void *container, Eina_File_Direct_Info *info, 
Eina_Stat *buf) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1, 2, 3);
 
+/**
+ * @brief Close all file descriptors that are open at or above the given fd
+ * @details This closes all open file descriptors that are equal to or of
+ *          higher value than the given inpit fd given. This is intended for
+ *          niche use like closing all open files just before exec()ing a
+ *          new process after calling fork(). The except_fd array can be NULL
+ *          if no fd's are to be skipped, but if some fd's are to skip being
+ *          closed then this will be an array of fd numbers being terminated
+ *          by a fd value of -1.
+ * 
+ * @param[in] fd The fd value to begin closing at
+ * @param[in] except_fd An array of fd's not to close terminated by -1 as the 
last invalid fd
+ * 
+ * @since 1.24
+ */
+EAPI void eina_file_close_from(int fd, int *except_fd);
+
 /**
  * @brief Generates and creates a uniquely named temporary file from a 
template name.
  *        The generated file is opened with the open(2) @c O_EXCL flag.

-- 


Reply via email to