1 /*========================== begin_copyright_notice ============================ 2 3 Copyright (C) 2017-2021 Intel Corporation 4 5 SPDX-License-Identifier: MIT 6 7 ============================= end_copyright_notice ===========================*/ 8 9 #include "SysUtils.hpp" 10 #include <sstream> 11 #include <fstream> 12 #include <sys/stat.h> 13 #include "Probe/Assertion.h" 14 15 using namespace std; 16 17 #ifndef S_ISDIR 18 #define S_ISDIR(flags) (((flags)&S_IFDIR)==S_IFDIR) 19 #endif 20 21 namespace IGC 22 { 23 namespace SysUtils 24 { 25 //implementation details 26 namespace 27 { 28 template <typename T> MakeStrImpl(ostream & ss,T const & t)29 inline void MakeStrImpl(ostream& ss, T const& t) 30 { 31 ss << t; 32 } 33 34 template <typename T1, typename... T> MakeStrImpl(ostream & ss,T1 const & t1,T const &...args)35 inline void MakeStrImpl(ostream& ss, T1 const& t1, T const&... args) 36 { 37 MakeStrImpl(ss << t1, args...); 38 } 39 } 40 41 //makes single string from args, using stringstream 42 template <typename... T> MakeStr(T const &...args)43 string MakeStr(T const&... args) 44 { 45 if (sizeof...(args) == 0) // MakeStr() == "" 46 return ""; 47 48 stringstream ss; 49 MakeStrImpl(ss, args...); //see functions above 50 return ss.str(); 51 } 52 GetProcessName()53 string GetProcessName() 54 { 55 string ret; 56 57 #if defined (__linux__) 58 ifstream in(MakeStr("/proc/", getpid(), "/cmdline"), ios::in); 59 IGC_ASSERT_MESSAGE(in.is_open(), "Can not open cmdline pseudo file for current process"); 60 61 //in cmdline arguments are separated with \0 62 getline(in, ret, '\0'); 63 IGC_ASSERT_MESSAGE(in.good(), "Error reading from cmdline pseudo file"); 64 65 #elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ 66 defined(__OpenBSD__) || defined(__sun) 67 // KERN_PROC_ARGS returns similar value to /proc/<pid>/cmdline but as 68 // neither invocation path nor arguments are used just ask libc 69 ret = getprogname(); 70 #elif defined(_WIN64) || defined(_WIN32) 71 ret.resize(MAX_PATH); 72 DWORD size = ::GetModuleFileNameA(NULL, &ret[0], ret.size()); 73 IGC_ASSERT_MESSAGE(size < ret.size(), "Windows path can have MAX_PATH characters max"); 74 ret.resize(size); 75 #else 76 ret = "unknownProcess"; 77 #endif 78 79 auto pos = ret.rfind('/'); 80 if (pos != ret.npos) 81 ret = ret.substr(pos + 1); 82 return ret; 83 } 84 CreateDir(string basedir,bool addprocessdir,bool addpid,string * full_path)85 bool CreateDir(string basedir, bool addprocessdir, bool addpid, string* full_path) 86 { 87 UnifyDirSeparators(basedir); 88 89 if (addprocessdir) 90 { 91 if (!basedir.empty() && basedir.back() != '/') 92 basedir.push_back('/'); 93 94 basedir += GetProcessName(); 95 96 if (addpid) 97 basedir += MakeStr("_", GetProcessId()); 98 } 99 100 if (basedir.empty()) 101 { 102 if (full_path != nullptr) 103 *full_path = ""; 104 return true; 105 } 106 107 if (basedir.back() != '/') 108 basedir.push_back('/'); 109 110 struct stat statbuf; 111 112 #ifdef _WIN32 113 auto pos = basedir.find('/', (basedir.size() > 2 && basedir[1] == ':') ? 3 : 0); //on windows, ignore drive letter 114 #else 115 auto pos = basedir.find('/', (basedir[0] == '/' ? 1 : 0)); //on linux, ignore root / 116 #endif 117 118 while (pos != basedir.npos) 119 { 120 basedir[pos] = 0; 121 122 if (stat(basedir.data(), &statbuf) != 0) //dir doesnt exist 123 { 124 if (!CreateSingleDir(basedir.data())) //couldn't create 125 return false; 126 } 127 else if (!S_ISDIR(statbuf.st_mode)) //exists but isnt dir 128 return false; 129 130 basedir[pos] = '/'; 131 pos = basedir.find('/', pos + 1); 132 } 133 134 if (full_path != nullptr) 135 *full_path = basedir; 136 137 return true; 138 } 139 } 140 } 141