From a75700d86e2a0245d28fdf2762638d07efc549a0 Mon Sep 17 00:00:00 2001 From: Sami Kerola Date: Wed, 2 Dec 2020 22:56:16 +0000 Subject: [PATCH] lib/fileutils: make close_all_fds() to be similar with close_range() 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 Reference: https://github.com/karelzak/util-linux/pull/1205#discussion_r534080128 Signed-off-by: Sami Kerola --- include/fileutils.h | 6 ++++-- lib/fileutils.c | 39 +++++++++++++++++++-------------------- login-utils/login.c | 7 +------ 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/include/fileutils.h b/include/fileutils.h index 1de214bcad..7047ac5ccb 100644 --- a/include/fileutils.h +++ b/include/fileutils.h @@ -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) diff --git a/lib/fileutils.c b/lib/fileutils.c index 9da906ae09..c16ecf8a83 100644 --- a/lib/fileutils.c +++ b/lib/fileutils.c @@ -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) diff --git a/login-utils/login.c b/login-utils/login.c index ec8ce0fdf6..644bdd31d2 100644 --- a/login-utils/login.c +++ b/login-utils/login.c @@ -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 } -- 2.47.3