1- // #include <experimental/filesystem >
2- #include < boost/filesystem.hpp >
1+ #include < iostream >
2+ #include < string >
33#include < sstream>
44#include < fstream>
55
66#include " NativeCore.hpp"
77
8+ // std::filesystem library doesn't work @Ubuntu 16.10, read_symlink() always fails.
9+ // #define USE_STD_FILESYSTEM
10+ #ifdef USE_STD_FILESYSTEM
11+ #include < experimental/filesystem>
12+ #else
13+ #include < dirent.h>
14+ #include < sys/stat.h>
15+ #include < unistd.h>
16+
17+ class path
18+ {
19+ public:
20+ path () = default ;
21+
22+ path (const char * _path)
23+ : path(std::string(_path))
24+ {
25+ }
26+
27+ path (const std::string& _path)
28+ : buf(_path)
29+ {
30+ }
31+
32+ path (const path&) = default ;
33+
34+ path& append (const std::string& part)
35+ {
36+ if (buf.back () != separator)
37+ {
38+ buf += separator;
39+ }
40+ buf += part;
41+
42+ return *this ;
43+ }
44+
45+ path& operator /=(const path& p)
46+ {
47+ append (p.buf );
48+
49+ return *this ;
50+ }
51+
52+ const std::string& string () const
53+ {
54+ return buf;
55+ }
56+
57+ const char * c_str () const
58+ {
59+ return buf.c_str ();
60+ }
61+
62+ private:
63+ static const char separator = ' /' ;
64+
65+ std::string buf;
66+ };
67+
68+ inline path operator /(const path& lhs, const path& rhs)
69+ {
70+ return path (lhs) /= rhs;
71+ }
72+
73+ enum class FileType
74+ {
75+ Unknown,
76+
77+ File,
78+ Directory,
79+ Symlink
80+ };
81+
82+ FileType file_type (const path& p)
83+ {
84+ struct stat path_stat = {};
85+ if (::lstat (p.c_str (), &path_stat) == 0 )
86+ {
87+ if (S_ISREG (path_stat.st_mode ))
88+ {
89+ return FileType::File;
90+ }
91+ else if (S_ISDIR (path_stat.st_mode ))
92+ {
93+ return FileType::Directory;
94+ }
95+ else if (S_ISLNK (path_stat.st_mode ))
96+ {
97+ return FileType::Symlink;
98+ }
99+ }
100+
101+ return FileType::Unknown;
102+ }
103+
104+ inline bool is_directory (const path& p)
105+ {
106+ return file_type (p) == FileType::Directory;
107+ }
108+
109+ inline bool is_symlink (const path& p)
110+ {
111+ return file_type (p) == FileType::Symlink;
112+ }
113+
114+ bool read_symlink (const path& p, path& out_p)
115+ {
116+ std::string temp (64 , ' \0 ' );
117+
118+ for (;; temp.resize (temp.size () * 2 ))
119+ {
120+ ssize_t result;
121+ if ((result = ::readlink (p.c_str (), /* temp.data()*/ &temp[0 ], temp.size ())) == -1 )
122+ {
123+ return false ;
124+ }
125+ else
126+ {
127+ if (result != (ssize_t )temp.size ())
128+ {
129+ out_p = path (std::string (temp.begin (), temp.begin () + result));
130+
131+ return true ;
132+ }
133+ }
134+ }
135+ }
136+
137+ #endif
138+
8139bool is_number (const std::string& s)
9140{
10- std::string::const_iterator it = s.begin ();
11- while ( it != s.end () && std::isdigit (*it)) ++it;
141+ auto it = s.begin ();
142+ for (; it != s.end () && std::isdigit (*it); ++it) ;
12143 return !s.empty () && it == s.end ();
13144}
14145
@@ -58,41 +189,61 @@ Platform GetProcessPlatform(const std::string& auxvPath)
58189
59190extern " C" void EnumerateProcesses (EnumerateProcessCallback callbackProcess)
60191{
61- // using namespace std::experimental::filesystem;
62- // using namespace std;
63-
64- using namespace boost ::filesystem;
65- using namespace boost ::system;
66-
67192 if (callbackProcess == nullptr )
68193 {
69194 return ;
70195 }
71196
72- path proc (" /proc" );
197+ #ifdef USE_STD_FILESYSTEM
198+ using namespace std ::experimental::filesystem;
199+ using namespace std ;
73200
74- if (is_directory (proc))
201+ path procPath (" /proc" );
202+ if (is_directory (procPath))
75203 {
76- for (auto & p : directory_iterator (proc ))
204+ for (auto & d : directory_iterator (procPath ))
77205 {
78- if (is_directory (p ))
206+ if (is_directory (d ))
79207 {
80- auto processPath = p .path ();
208+ auto pidPath = d .path ();
81209
82210 auto name = processPath.filename ().string ();
83211 if (is_number (name))
84212 {
85- size_t pid = parse_type<size_t >(name);
86-
87213 auto exeSymLink = processPath / " exe" ;
88214 if (is_symlink (symlink_status (exeSymLink)))
89215 {
90216 error_code ec;
91- auto e = read_symlink (exeSymLink, ec);
92-
217+ auto linkPath = read_symlink (exeSymLink, ec).string ();
93218 if (!ec)
94219 {
95- auto auxvPath = processPath / " auxv" ;
220+ #else
221+ path procPath (" /proc" );
222+ if (is_directory (procPath))
223+ {
224+ auto directory = opendir (procPath.c_str ());
225+ if (directory == nullptr )
226+ {
227+ return ;
228+ }
229+
230+ struct dirent *entry;
231+ while ((entry = readdir (directory)) != nullptr )
232+ {
233+ auto pidPath = procPath / entry->d_name ;
234+ if (is_directory (pidPath))
235+ {
236+ std::string name (entry->d_name );
237+ if (is_number (name))
238+ {
239+ auto exePath = pidPath / " exe" ;
240+ if (is_symlink (exePath))
241+ {
242+ path linkPath;
243+ if (read_symlink (exePath, linkPath))
244+ {
245+ #endif
246+ auto auxvPath = pidPath / " auxv" ;
96247
97248 auto platform = GetProcessPlatform (auxvPath.string ());
98249#ifdef NATIVE_CORE_64
@@ -102,8 +253,8 @@ extern "C" void EnumerateProcesses(EnumerateProcessCallback callbackProcess)
102253#endif
103254 {
104255 EnumerateProcessData data = {};
105- data.Id = pid ;
106- MultiByteToUnicode (e. string () .c_str (), data.ModulePath , PATH_MAXIMUM_LENGTH);
256+ data.Id = parse_type< size_t >(name) ;
257+ MultiByteToUnicode (linkPath .c_str (), data.ModulePath , PATH_MAXIMUM_LENGTH);
107258
108259 callbackProcess (&data);
109260 }
0 commit comments