File indexing completed on 2025-01-18 09:50:10
0001
0002
0003
0004
0005
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, 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
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
0164 filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
0165 {
0166 filesystem::path path;
0167
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 }
0237
0238 BOOST_PROCESS_V2_END_NAMESPACE
0239
0240 #endif
0241