]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lib/fileutils: make close_all_fds() to be similar with close_range()
authorSami Kerola <kerolasa@iki.fi>
Wed, 2 Dec 2020 22:56:16 +0000 (22:56 +0000)
committerSami Kerola <kerolasa@iki.fi>
Thu, 3 Dec 2020 20:09:14 +0000 (20:09 +0000)
The util-linux close_all_fds() serves the same purpose as close_range()
that will over time obsolete local implementation completely.  For
upcoming few years it is best to have a fallback that uses same input
arguments as the new system call.  That allows surrounding code and
variables not to be affected by version of mass file descriptor closing
function.

Proposed-by: Karel Zak <kzak@redhat.com>
Reference: https://github.com/karelzak/util-linux/pull/1205#discussion_r534080128
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
include/fileutils.h
lib/fileutils.c
login-utils/login.c

index 1de214bcad2a93a5df9c8bd48e9ab78a612583b3..7047ac5ccb1d572db03195c9fa22419086006bd4 100644 (file)
@@ -53,7 +53,7 @@ static inline int is_same_inode(const int fd, const struct stat *st)
 }
 
 extern int dup_fd_cloexec(int oldfd, int lowfd);
-extern int get_fd_tabsize(void);
+extern unsigned int get_fd_tabsize(void);
 
 extern int mkdir_p(const char *path, mode_t mode);
 extern char *stripoff_last_component(char *path);
@@ -86,7 +86,9 @@ static inline int close_range(unsigned int first, unsigned int last)
 # endif        /* SYS_close_range */
 #endif /* __linux__ */
 
-extern void close_all_fds(const int exclude[], size_t exsz);
+#ifndef HAVE_CLOSE_RANGE
+extern void close_all_fds(unsigned int first, unsigned int last);
+#endif
 
 #define UL_COPY_READ_ERROR (-1)
 #define UL_COPY_WRITE_ERROR (-2)
index 9da906ae09279d0512206e35dca17cd23aa38298..c16ecf8a833a2acc20a3d68d9492b71b112d9fec 100644 (file)
@@ -110,7 +110,7 @@ unwind:
 /*
  * portable getdtablesize()
  */
-int get_fd_tabsize(void)
+unsigned int get_fd_tabsize(void)
 {
        int m;
 
@@ -129,18 +129,8 @@ int get_fd_tabsize(void)
        return m;
 }
 
-static inline int in_set(int x, const int set[], size_t setsz)
-{
-       size_t i;
-
-       for (i = 0; i < setsz; i++) {
-               if (set[i] == x)
-                       return 1;
-       }
-       return 0;
-}
-
-void close_all_fds(const int exclude[], size_t exsz)
+#ifndef HAVE_CLOSE_RANGE
+void close_all_fds(unsigned int first, unsigned int last)
 {
        struct dirent *d;
        DIR *dir;
@@ -149,29 +139,34 @@ void close_all_fds(const int exclude[], size_t exsz)
        if (dir) {
                while ((d = xreaddir(dir))) {
                        char *end;
-                       int fd;
+                       unsigned int fd;
+                       int dfd;
 
                        errno = 0;
-                       fd = strtol(d->d_name, &end, 10);
+                       fd = strtoul(d->d_name, &end, 10);
 
                        if (errno || end == d->d_name || !end || *end)
                                continue;
-                       if (dirfd(dir) == fd)
+                       dfd = dirfd(dir);
+                       if (dfd < 0)
                                continue;
-                       if (in_set(fd, exclude, exsz))
+                       if ((unsigned int)dfd == fd)
+                               continue;
+                       if (fd < first || last < fd)
                                continue;
                        close(fd);
                }
                closedir(dir);
        } else {
-               int fd, tbsz = get_fd_tabsize();
+               unsigned fd, tbsz = get_fd_tabsize();
 
                for (fd = 0; fd < tbsz; fd++) {
-                       if (!in_set(fd, exclude, exsz))
+                       if (first <= fd && fd <= last)
                                close(fd);
                }
        }
 }
+#endif
 
 #ifdef TEST_PROGRAM_FILEUTILS
 int main(int argc, char *argv[])
@@ -196,7 +191,11 @@ int main(int argc, char *argv[])
                ignore_result( dup(STDIN_FILENO) );
                ignore_result( dup(STDIN_FILENO) );
 
-               close_all_fds(wanted_fds, ARRAY_SIZE(wanted_fds));
+# ifdef HAVE_CLOSE_RANGE
+               close_range(STDERR_FILENO + 1, ~0U);
+# else
+               close_all_fds(STDERR_FILENO + 1, ~0U);
+# endif
        } else if (strcmp(argv[1], "--copy-file") == 0) {
                int ret = ul_copy_file(STDIN_FILENO, STDOUT_FILENO);
                if (ret == UL_COPY_READ_ERROR)
index ec8ce0fdf6b0d0655a2029c67017b7196445a3da..644bdd31d2db5d33f89df746bc9445bb56868d7c 100644 (file)
@@ -1294,11 +1294,6 @@ static void initialize(int argc, char **argv, struct login_context *cxt)
                {"version", no_argument, NULL, 'V'},
                {NULL, 0, NULL, 0}
        };
-#ifndef HAVE_CLOSE_RANGE
-       const int wanted_fds[] = {
-               STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO
-       };
-#endif
 
        timeout = (unsigned int)getlogindefs_num("LOGIN_TIMEOUT", LOGIN_TIMEOUT);
 
@@ -1370,7 +1365,7 @@ static void initialize(int argc, char **argv, struct login_context *cxt)
 #ifdef HAVE_CLOSE_RANGE
        close_range(STDERR_FILENO + 1, ~0U);
 #else
-       close_all_fds(wanted_fds, ARRAY_SIZE(wanted_fds));
+       close_all_fds(STDERR_FILENO + 1, ~0U);
 #endif
 }