Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // Copyright (c) 2022 Klemens D. Morgenstern
0002 // Copyright (c) 2022 Samuel Venable
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 #ifndef BOOST_PROCESS_V2_IMPL_CWD_IPP
0007 #define BOOST_PROCESS_V2_IMPL_CWD_IPP
0008 
0009 #include <boost/process/v2/detail/config.hpp>
0010 #include <boost/process/v2/detail/last_error.hpp>
0011 #include <boost/process/v2/detail/throw_error.hpp>
0012 #include <boost/process/v2/ext/detail/proc_info.hpp>
0013 #include <boost/process/v2/ext/cwd.hpp>
0014 
0015 #include <string>
0016 
0017 #if defined(BOOST_PROCESS_V2_WINDOWS)
0018 #include <windows.h>
0019 #else
0020 #include <climits>
0021 #endif
0022 
0023 #if (defined(__APPLE__) && defined(__MACH__))
0024 #include <sys/proc_info.h>
0025 #include <libproc.h>
0026 #endif
0027 
0028 #if (defined(BOOST_PROCESS_V2_WINDOWS) || defined(__linux__) || defined(__ANDROID__) || defined(__sun))
0029 #include <cstdlib>
0030 #endif
0031 
0032 #if defined(__FreeBSD__)
0033 #include <sys/socket.h>
0034 #include <sys/sysctl.h>
0035 #include <sys/param.h>
0036 #include <sys/queue.h>
0037 #include <sys/user.h>
0038 #include <libprocstat.h>
0039 #endif
0040 
0041 #if (defined(__NetBSD__) || defined(__OpenBSD__))
0042 #include <sys/types.h>
0043 #include <sys/sysctl.h>
0044 #endif
0045 
0046 #if defined(__DragonFly__)
0047 #include <cstring>
0048 #include <cstdio>
0049 #endif
0050 
0051 #ifdef BOOST_PROCESS_USE_STD_FS
0052 namespace filesystem = std::filesystem;
0053 #else
0054 namespace filesystem = boost::filesystem;
0055 #endif
0056 
0057 BOOST_PROCESS_V2_BEGIN_NAMESPACE
0058 
0059 namespace ext {
0060 
0061 #if defined(BOOST_PROCESS_V2_WINDOWS)
0062 
0063 filesystem::path cwd(HANDLE proc, boost::system::error_code & ec)
0064 {
0065     auto buffer = boost::process::v2::detail::ext::cwd_cmd_from_proc(proc, 1/*=MEMCWD*/, ec);
0066     if (!buffer.empty())
0067       return filesystem::canonical(buffer, ec);
0068     else 
0069         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0070     return "";
0071 }
0072 
0073 filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
0074 {
0075     struct del
0076     {
0077         void operator()(HANDLE h)
0078         {
0079             ::CloseHandle(h);
0080         };
0081     };
0082     std::unique_ptr<void, del> proc{detail::ext::open_process_with_debug_privilege(pid, ec)};
0083     if (proc == nullptr)
0084         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0085     else
0086         return cwd(proc.get(), ec);
0087     return {};
0088 }
0089 
0090 filesystem::path cwd(HANDLE proc)
0091 {
0092     boost::system::error_code ec;
0093     auto res = cwd(proc, ec);
0094     if (ec)
0095         detail::throw_error(ec, "cwd");
0096     return res;
0097 }
0098 
0099 #elif (defined(__APPLE__) && defined(__MACH__))
0100 
0101 filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
0102 {
0103     proc_vnodepathinfo vpi;
0104     if (proc_pidinfo(pid, PROC_PIDVNODEPATHINFO, 0, &vpi, sizeof(vpi)) > 0)
0105         return filesystem::canonical(vpi.pvi_cdir.vip_path, ec);
0106     else
0107       BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0108     return "";
0109 }
0110 
0111 #elif (defined(__linux__) || defined(__ANDROID__) || defined(__sun))
0112 
0113 filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
0114 {
0115 #if (defined(__linux__) || defined(__ANDROID__))
0116     return filesystem::canonical(
0117             filesystem::path("/proc") / std::to_string(pid) / "cwd", ec
0118             );
0119 #elif defined(__sun)
0120     return fileystem::canonical(
0121             filesystem::path("/proc") / std::to_string(pid) / "path/cwd", ec
0122             );
0123 #endif
0124 }
0125 
0126 #elif defined(__FreeBSD__)
0127 
0128 // FIXME: Add error handling.
0129 filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec) 
0130 {
0131     filesystem::path path;
0132     unsigned cntp = 0;
0133     procstat *proc_stat = procstat_open_sysctl();
0134     if (proc_stat) {
0135         kinfo_proc *proc_info = procstat_getprocs(proc_stat, KERN_PROC_PID, pid, &cntp);
0136         if (proc_info) {
0137             filestat_list *head = procstat_getfiles(proc_stat, proc_info, 0);
0138             if (head) {
0139                 filestat *fst = nullptr;
0140                 STAILQ_FOREACH(fst, head, next) {
0141                     if (fst->fs_uflags & PS_FST_UFLAG_CDIR) 
0142                     {
0143                         path = filesystem::canonical(fst->fs_path, ec);
0144                     }
0145                 }
0146                 procstat_freefiles(proc_stat, head);
0147             }
0148             else
0149                 BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0150             procstat_freeprocs(proc_stat, proc_info);
0151         }
0152         else
0153             BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0154         procstat_close(proc_stat);
0155     }
0156     else
0157          BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0158     return path;
0159 }
0160 
0161 #elif defined(__DragonFly__)
0162 
0163 // FIXME: Add error handling.
0164 filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec) 
0165 {
0166     filesystem::path path;
0167     /* Probably the hackiest thing ever we are doing here, because the "official" API is broken OS-level. */
0168     FILE *fp = popen(("pos=`ans=\\`/usr/bin/fstat -w -p " + std::to_string(pid) + " | /usr/bin/sed -n 1p\\`; " +
0169         "/usr/bin/awk -v ans=\"$ans\" 'BEGIN{print index(ans, \"INUM\")}'`; str=`/usr/bin/fstat -w -p " + 
0170         std::to_string(pid) + " | /usr/bin/sed -n 3p`; /usr/bin/awk -v str=\"$str\" -v pos=\"$pos\" " +
0171         "'BEGIN{print substr(str, 0, pos + 4)}' | /usr/bin/awk 'NF{NF--};1 {$1=$2=$3=$4=\"\"; print" +
0172         " substr($0, 5)'}").c_str(), "r");
0173     if (fp) 
0174     {
0175         char buffer[PATH_MAX];
0176         if (fgets(buffer, sizeof(buffer), fp)) 
0177         {
0178             std::string str = buffer;
0179             std::size_t pos = str.find("\n", strlen(buffer) - 1);
0180             if (pos != std::string::npos) 
0181             {
0182                 str.replace(pos, 1, "");
0183             }
0184             path = filesystem::canonical(str.c_str(), ec);
0185         }
0186         else
0187             BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0188         pclose(fp);
0189     }
0190     else
0191         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0192     return path;
0193 }
0194 
0195 #elif (defined(__NetBSD__) || defined(__OpenBSD__))
0196 
0197 filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
0198 {
0199     std::string path;
0200 #if defined(__NetBSD__)
0201     int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_CWD};
0202     const std::size_t sz = 4;
0203 #elif defined(__OpenBSD__)
0204     int mib[3] = {CTL_KERN, KERN_PROC_CWD, pid};
0205     const std::size_t sz = 3;
0206 #endif
0207     std::size_t len = 0;
0208     if (sysctl(mib, sz, nullptr, &len, nullptr, 0) == 0) 
0209     {
0210         std::string strbuff;
0211         strbuff.resize(len);
0212         if (sysctl(mib, 4, &strbuff[0], &len, nullptr, 0) == 0)
0213         {
0214             filesystem::canonical(strbuff, ec);
0215         }
0216         else
0217             BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0218     }
0219 
0220     return "";
0221 }
0222 
0223 #else
0224 #error "Platform not supported"
0225 #endif
0226 
0227 filesystem::path cwd(boost::process::v2::pid_type pid)
0228 {
0229     boost::system::error_code ec;
0230     auto res = cwd(pid, ec);
0231     if (ec)
0232         detail::throw_error(ec, "cwd");
0233     return res;
0234 }
0235 
0236 } // namespace ext
0237 
0238 BOOST_PROCESS_V2_END_NAMESPACE
0239 
0240 #endif // BOOST_PROCESS_V2_IMPL_CWD_IPP
0241