Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:11

0001 //
0002 // boost/process/v2/posix/detail/close_handles.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_PROCESS_V2_POSIX_DETAIL_CLOSE_HANDLES_IPP
0012 #define BOOST_PROCESS_V2_POSIX_DETAIL_CLOSE_HANDLES_IPP
0013 
0014 #include <boost/process/v2/detail/config.hpp>
0015 #include <boost/process/v2/detail/last_error.hpp>
0016 #include <boost/process/v2/posix/detail/close_handles.hpp>
0017 // linux has close_range since 5.19
0018 
0019 
0020 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
0021 
0022 // https://www.freebsd.org/cgi/man.cgi?query=close_range&apropos=0&sektion=0&manpath=FreeBSD+13.1-RELEASE+and+Ports&arch=default&format=html
0023 // https://man.netbsd.org/closefrom.3
0024 // __FreeBSD__
0025 // 
0026 // gives us
0027 //
0028 // int closefrom(int fd);
0029 // int close_range(u_int lowfd, u_int highfd, int flags);
0030 
0031 #include <unistd.h>
0032 #define BOOST_PROCESS_V2_HAS_CLOSE_RANGE_AND_CLOSEFROM 1 
0033 
0034 #elif defined(__sun)
0035 
0036 /*https://docs.oracle.com/cd/E36784_01/html/E36874/closefrom-3c.html
0037 
0038 int fdwalk(int (*func)(void *, int), void *cd);
0039 */
0040 
0041 #include <stdlib.h>
0042 #define BOOST_PROCESS_V2_HAS_PDFORK 1 
0043 
0044 #elif defined(__linux__)
0045 
0046 #include <linux/version.h>
0047 
0048 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,11,0)
0049 
0050 // https://man7.org/linux/man-pages/man2/close_range.2.html
0051 #include <linux/close_range.h>
0052 #define BOOST_PROCESS_V2_HAS_CLOSE_RANGE 1 
0053 #else 
0054 
0055 #include <dirent.h>
0056 
0057 #endif
0058 
0059 #else
0060 
0061 #include <dirent.h>
0062 
0063 #endif
0064 
0065 BOOST_PROCESS_V2_BEGIN_NAMESPACE
0066 
0067 namespace posix
0068 {
0069 
0070 namespace detail
0071 {
0072 
0073 #if defined(BOOST_PROCESS_V2_HAS_PDFORK)
0074 
0075 void close_all(const std::vector<int> & whitelist, error_code & ec)
0076 {
0077     fdwalk(+[](void * p, int fd)
0078            {
0079                 const auto & wl = *static_cast<const std::vector<int>*>(p);
0080                 if (std::find(wl.begin(), wl.end(), fd) == wl.end())
0081                     return ::close(fd);
0082                 else 
0083                     return 0;
0084            }, const_cast<void*>(static_cast<const void*>(&whitelist)) );
0085     ec = BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error();
0086 }
0087 
0088 #elif defined(BOOST_PROCESS_V2_HAS_CLOSE_RANGE_AND_CLOSEFROM)
0089 
0090 // freeBSD impl - whitelist must be ordered
0091 void close_all(const std::vector<int> & whitelist, error_code & ec)
0092 {
0093     //the most common scenario is whitelist = {0,1,2}
0094     if (!whitelist.empty())
0095     {
0096         if (whitelist.front() != 0)
0097             ::close_range(0, whitelist.front() - 1, 0);
0098 
0099         for (std::size_t idx = 0u; 
0100              idx < (whitelist.size() - 1u);
0101              idx++)
0102         {
0103             const auto mine = whitelist[idx];
0104             const auto next = whitelist[idx];
0105             if ((mine + 1) != next && (mine != next))
0106             {
0107                 ::close_range(mine + 1, next - 1, 0);
0108             }
0109         }
0110 
0111         ::closefrom(whitelist.back() + 1);
0112     }
0113     else
0114         ::closefrom(0);
0115 }
0116 
0117 #elif defined(BOOST_PROCESS_V2_HAS_CLOSE_RANGE)
0118 
0119 
0120 // linux impl - whitelist must be ordered
0121 void close_all(const std::vector<int> & whitelist, error_code & ec)
0122 {
0123 // https://patchwork.kernel.org/project/linux-fsdevel/cover/20200602204219.186620-1-christian.brauner@ubuntu.com/
0124     //the most common scenario is whitelist = {0,1,2}
0125     if (!whitelist.empty())
0126     {
0127         if (whitelist.front() != 0)
0128             ::close_range(0, whitelist.front() - 1, CLOSE_RANGE_UNSHARE);
0129 
0130         for (std::size_t idx = 0u; 
0131              idx < (whitelist.size() - 1u);
0132              idx++)
0133         {
0134             const auto mine = whitelist[idx];
0135             const auto next = whitelist[idx];
0136             if ((mine + 1) != next && (mine != next))
0137             {
0138                 ::close_range(mine + 1, next - 1, CLOSE_RANGE_UNSHARE);
0139             }
0140         }
0141 
0142         ::close_range(whitelist.back() + 1, std::numeric_limits<int>::max(), CLOSE_RANGE_UNSHARE);
0143     }
0144     else
0145         ::close_range(0, std::numeric_limits<int>::max(), CLOSE_RANGE_UNSHARE);
0146 }
0147 
0148 #else
0149 
0150 // default one
0151 void close_all(const std::vector<int> & whitelist, error_code & ec)
0152 {
0153     std::unique_ptr<DIR, void(*)(DIR*)> dir{::opendir("/dev/fd"), +[](DIR* p){::closedir(p);}};
0154     if (dir.get() == nullptr)
0155     {
0156         ec = BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error();
0157         return ;
0158     }
0159 
0160     auto dir_fd = ::dirfd(dir.get());
0161     if (dir_fd == -1)
0162     {
0163         ec = BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error();
0164         return ;
0165     }
0166 
0167     struct ::dirent * ent_p;
0168 
0169     while ((ent_p = ::readdir(dir.get())) != nullptr)
0170     {
0171         if (ent_p->d_name[0] == '.')
0172             continue;
0173 
0174         const auto conv = std::atoi(ent_p->d_name);
0175         if (conv == 0 && (ent_p->d_name[0] != '0' && ent_p->d_name[1] != '\0'))
0176             continue;
0177 
0178         if (conv == dir_fd 
0179             || (std::find(whitelist.begin(), whitelist.end(), conv) != whitelist.end()))
0180             continue;
0181 
0182         ::close(conv);
0183     }
0184 }
0185 
0186 #endif
0187 
0188 }
0189 
0190 }
0191 
0192 BOOST_PROCESS_V2_END_NAMESPACE
0193 
0194 #endif //BOOST_PROCESS_V2_POSIX_DETAIL_CLOSE_HANDLES_IPP