Path: blob/main/tools/build/cross-build/closefrom.c
39536 views
/*1* Copyright (c) 2004-2005, 2007, 2010, 2012-20142* Todd C. Miller <[email protected]>3*4* Permission to use, copy, modify, and distribute this software for any5* purpose with or without fee is hereby granted, provided that the above6* copyright notice and this permission notice appear in all copies.7*8* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES9* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF10* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR11* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES12* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN13* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF14* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.15*/1617// #include <config.h>1819#include <sys/types.h>20#include <unistd.h>21#include <stdio.h>22#ifdef STDC_HEADERS23# include <stdlib.h>24# include <stddef.h>25#else26# ifdef HAVE_STDLIB_H27# include <stdlib.h>28# endif29#endif /* STDC_HEADERS */30#include <fcntl.h>31#include <limits.h>32#ifdef HAVE_PSTAT_GETPROC33# include <sys/param.h>34# include <sys/pstat.h>35#else36# ifdef HAVE_DIRENT_H37# include <dirent.h>38# define NAMLEN(dirent) strlen((dirent)->d_name)39# else40# define dirent direct41# define NAMLEN(dirent) (dirent)->d_namlen42# ifdef HAVE_SYS_NDIR_H43# include <sys/ndir.h>44# endif45# ifdef HAVE_SYS_DIR_H46# include <sys/dir.h>47# endif48# ifdef HAVE_NDIR_H49# include <ndir.h>50# endif51# endif52#endif5354#ifndef OPEN_MAX55# define OPEN_MAX 25656#endif5758#if defined(HAVE_FCNTL_CLOSEM) && !defined(HAVE_DIRFD)59# define closefrom closefrom_fallback60#endif6162static inline void63closefrom_close(int fd)64{65#ifdef __APPLE__66/* Avoid potential libdispatch crash when we close its fds. */67(void)fcntl(fd, F_SETFD, FD_CLOEXEC);68#else69(void)close(fd);70#endif71}7273/*74* Close all file descriptors greater than or equal to lowfd.75* This is the expensive (fallback) method.76*/77void78closefrom_fallback(int lowfd)79{80long fd, maxfd;8182/*83* Fall back on sysconf() or getdtablesize(). We avoid checking84* resource limits since it is possible to open a file descriptor85* and then drop the rlimit such that it is below the open fd.86*/87#ifdef HAVE_SYSCONF88maxfd = sysconf(_SC_OPEN_MAX);89#else90maxfd = getdtablesize();91#endif /* HAVE_SYSCONF */92if (maxfd < 0)93maxfd = OPEN_MAX;9495for (fd = lowfd; fd < maxfd; fd++)96closefrom_close(fd);97}9899/*100* Close all file descriptors greater than or equal to lowfd.101* We try the fast way first, falling back on the slow method.102*/103#if defined(HAVE_FCNTL_CLOSEM)104void105closefrom(int lowfd)106{107if (fcntl(lowfd, F_CLOSEM, 0) == -1)108closefrom_fallback(lowfd);109}110#elif defined(HAVE_PSTAT_GETPROC)111void112closefrom(int lowfd)113{114struct pst_status pstat;115int fd;116117if (pstat_getproc(&pstat, sizeof(pstat), 0, getpid()) != -1) {118for (fd = lowfd; fd <= pstat.pst_highestfd; fd++)119(void)close(fd);120} else {121closefrom_fallback(lowfd);122}123}124#elif defined(HAVE_DIRFD)125static int126closefrom_procfs(int lowfd)127{128const char *path;129DIR *dirp;130struct dirent *dent;131int *fd_array = NULL;132int fd_array_used = 0;133int fd_array_size = 0;134int ret = 0;135int i;136137/* Use /proc/self/fd (or /dev/fd on FreeBSD) if it exists. */138# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)139path = "/dev/fd";140# else141path = "/proc/self/fd";142# endif143dirp = opendir(path);144if (dirp == NULL)145return -1;146147while ((dent = readdir(dirp)) != NULL) {148const char *errstr;149int fd;150151fd = strtonum(dent->d_name, lowfd, INT_MAX, &errstr);152if (errstr != NULL || fd == dirfd(dirp))153continue;154155if (fd_array_used >= fd_array_size) {156int *ptr;157158if (fd_array_size > 0)159fd_array_size *= 2;160else161fd_array_size = 32;162163ptr = reallocarray(fd_array, fd_array_size, sizeof(int));164if (ptr == NULL) {165ret = -1;166break;167}168fd_array = ptr;169}170171fd_array[fd_array_used++] = fd;172}173174for (i = 0; i < fd_array_used; i++)175closefrom_close(fd_array[i]);176177free(fd_array);178(void)closedir(dirp);179180return ret;181}182183void184closefrom(int lowfd)185{186if (closefrom_procfs(lowfd) == 0)187return;188189closefrom_fallback(lowfd);190}191#endif /* HAVE_FCNTL_CLOSEM */192193194