/src/PcapPlusPlus/Common++/src/SystemUtils.cpp
Line | Count | Source |
1 | | #include "SystemUtils.h" |
2 | | #include "EndianPortable.h" |
3 | | |
4 | | #ifndef _MSC_VER |
5 | | # include <unistd.h> |
6 | | #endif |
7 | | #include <stdexcept> |
8 | | #include <memory> |
9 | | #include <array> |
10 | | #include <iostream> |
11 | | #include <mutex> |
12 | | #include <cstring> |
13 | | #include <csignal> |
14 | | #include <sys/stat.h> |
15 | | #include <thread> |
16 | | #if defined(__APPLE__) |
17 | | # include <mach/clock.h> |
18 | | # include <mach/mach.h> |
19 | | #endif |
20 | | |
21 | | #if defined(_WIN32) |
22 | | # include <Windows.h> |
23 | | # define POPEN _popen |
24 | | # define PCLOSE _pclose |
25 | | #else |
26 | 0 | # define POPEN popen |
27 | 0 | # define PCLOSE pclose |
28 | | #endif |
29 | | |
30 | | #ifdef _MSC_VER |
31 | | # include <chrono> |
32 | | int gettimeofday(struct timeval* tp, struct timezone* tzp) |
33 | | { |
34 | | |
35 | | auto now = std::chrono::system_clock::now(); |
36 | | auto duration = now.time_since_epoch(); |
37 | | |
38 | | auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration); |
39 | | auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(duration - seconds); |
40 | | |
41 | | tp->tv_sec = static_cast<long>(seconds.count()); |
42 | | tp->tv_usec = static_cast<long>(microseconds.count()); |
43 | | return 0; |
44 | | } |
45 | | #endif |
46 | | |
47 | | /// @cond PCPP_INTERNAL |
48 | | |
49 | | namespace |
50 | | { |
51 | | |
52 | | /// @class PcloseDeleter |
53 | | /// A deleter that cleans up a FILE handle using pclose. |
54 | | struct PcloseDeleter |
55 | | { |
56 | | void operator()(FILE* ptr) const noexcept |
57 | 0 | { |
58 | 0 | PCLOSE(ptr); |
59 | 0 | } |
60 | | }; |
61 | | } // namespace |
62 | | |
63 | | /// @endcond |
64 | | |
65 | | namespace pcpp |
66 | | { |
67 | | |
68 | | const SystemCore SystemCores::Core0 = { 0x01, 0 }; |
69 | | const SystemCore SystemCores::Core1 = { 0x02, 1 }; |
70 | | const SystemCore SystemCores::Core2 = { 0x04, 2 }; |
71 | | const SystemCore SystemCores::Core3 = { 0x08, 3 }; |
72 | | const SystemCore SystemCores::Core4 = { 0x10, 4 }; |
73 | | const SystemCore SystemCores::Core5 = { 0x20, 5 }; |
74 | | const SystemCore SystemCores::Core6 = { 0x40, 6 }; |
75 | | const SystemCore SystemCores::Core7 = { 0x80, 7 }; |
76 | | const SystemCore SystemCores::Core8 = { 0x100, 8 }; |
77 | | const SystemCore SystemCores::Core9 = { 0x200, 9 }; |
78 | | const SystemCore SystemCores::Core10 = { 0x400, 10 }; |
79 | | const SystemCore SystemCores::Core11 = { 0x800, 11 }; |
80 | | const SystemCore SystemCores::Core12 = { 0x1000, 12 }; |
81 | | const SystemCore SystemCores::Core13 = { 0x2000, 13 }; |
82 | | const SystemCore SystemCores::Core14 = { 0x4000, 14 }; |
83 | | const SystemCore SystemCores::Core15 = { 0x8000, 15 }; |
84 | | const SystemCore SystemCores::Core16 = { 0x10000, 16 }; |
85 | | const SystemCore SystemCores::Core17 = { 0x20000, 17 }; |
86 | | const SystemCore SystemCores::Core18 = { 0x40000, 18 }; |
87 | | const SystemCore SystemCores::Core19 = { 0x80000, 19 }; |
88 | | const SystemCore SystemCores::Core20 = { 0x100000, 20 }; |
89 | | const SystemCore SystemCores::Core21 = { 0x200000, 21 }; |
90 | | const SystemCore SystemCores::Core22 = { 0x400000, 22 }; |
91 | | const SystemCore SystemCores::Core23 = { 0x800000, 23 }; |
92 | | const SystemCore SystemCores::Core24 = { 0x1000000, 24 }; |
93 | | const SystemCore SystemCores::Core25 = { 0x2000000, 25 }; |
94 | | const SystemCore SystemCores::Core26 = { 0x4000000, 26 }; |
95 | | const SystemCore SystemCores::Core27 = { 0x8000000, 27 }; |
96 | | const SystemCore SystemCores::Core28 = { 0x10000000, 28 }; |
97 | | const SystemCore SystemCores::Core29 = { 0x20000000, 29 }; |
98 | | const SystemCore SystemCores::Core30 = { 0x40000000, 30 }; |
99 | | const SystemCore SystemCores::Core31 = { 0x80000000, 31 }; |
100 | | |
101 | | const SystemCore SystemCores::IdToSystemCore[MAX_NUM_OF_CORES] = { |
102 | | SystemCores::Core0, SystemCores::Core1, SystemCores::Core2, SystemCores::Core3, SystemCores::Core4, |
103 | | SystemCores::Core5, SystemCores::Core6, SystemCores::Core7, SystemCores::Core8, SystemCores::Core9, |
104 | | SystemCores::Core10, SystemCores::Core11, SystemCores::Core12, SystemCores::Core13, SystemCores::Core14, |
105 | | SystemCores::Core15, SystemCores::Core16, SystemCores::Core17, SystemCores::Core18, SystemCores::Core19, |
106 | | SystemCores::Core20, SystemCores::Core21, SystemCores::Core22, SystemCores::Core23, SystemCores::Core24, |
107 | | SystemCores::Core25, SystemCores::Core26, SystemCores::Core27, SystemCores::Core28, SystemCores::Core29, |
108 | | SystemCores::Core30, SystemCores::Core31 |
109 | | }; |
110 | | |
111 | | int getNumOfCores() |
112 | 0 | { |
113 | | #if defined(_WIN32) |
114 | | SYSTEM_INFO sysinfo; |
115 | | GetSystemInfo(&sysinfo); |
116 | | return sysinfo.dwNumberOfProcessors; |
117 | | #else |
118 | 0 | return static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN)); |
119 | 0 | #endif |
120 | 0 | } |
121 | | |
122 | | CoreMask getCoreMaskForAllMachineCores() |
123 | 0 | { |
124 | 0 | const int numOfCores = getNumOfCores() < 32 ? getNumOfCores() : 32; |
125 | 0 | CoreMask result = 0; |
126 | 0 | for (int i = 0; i < numOfCores; i++) |
127 | 0 | { |
128 | 0 | result = result | SystemCores::IdToSystemCore[i].Mask; |
129 | 0 | } |
130 | |
|
131 | 0 | return result; |
132 | 0 | } |
133 | | |
134 | | CoreMask createCoreMaskFromCoreVector(const std::vector<SystemCore>& cores) |
135 | 0 | { |
136 | 0 | CoreMask result = 0; |
137 | 0 | for (const auto& core : cores) |
138 | 0 | { |
139 | | // cppcheck-suppress useStlAlgorithm |
140 | 0 | result |= core.Mask; |
141 | 0 | } |
142 | |
|
143 | 0 | return result; |
144 | 0 | } |
145 | | |
146 | | CoreMask createCoreMaskFromCoreIds(const std::vector<int>& coreIds) |
147 | 0 | { |
148 | 0 | CoreMask result = 0; |
149 | 0 | for (const auto& coreId : coreIds) |
150 | 0 | { |
151 | | // cppcheck-suppress useStlAlgorithm |
152 | 0 | result |= SystemCores::IdToSystemCore[coreId].Mask; |
153 | 0 | } |
154 | |
|
155 | 0 | return result; |
156 | 0 | } |
157 | | |
158 | | void createCoreVectorFromCoreMask(CoreMask coreMask, std::vector<SystemCore>& resultVec) |
159 | 0 | { |
160 | 0 | int idx = 0; |
161 | 0 | while (coreMask != 0) |
162 | 0 | { |
163 | 0 | if ((1 & coreMask) != 0U) |
164 | 0 | { |
165 | 0 | resultVec.push_back(SystemCores::IdToSystemCore[idx]); |
166 | 0 | } |
167 | |
|
168 | 0 | coreMask = coreMask >> 1; |
169 | 0 | ++idx; |
170 | 0 | } |
171 | 0 | } |
172 | | |
173 | | std::string executeShellCommand(const std::string& command) |
174 | 0 | { |
175 | 0 | const std::unique_ptr<FILE, PcloseDeleter> pipe = |
176 | 0 | std::unique_ptr<FILE, PcloseDeleter>(POPEN(command.c_str(), "r")); |
177 | 0 | if (!pipe) |
178 | 0 | { |
179 | 0 | throw std::runtime_error("Error executing command: " + command); |
180 | 0 | } |
181 | | |
182 | 0 | std::array<char, 128> buffer{}; |
183 | 0 | std::string result; |
184 | 0 | while (feof(pipe.get()) == 0) |
185 | 0 | { |
186 | 0 | if (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) |
187 | 0 | { |
188 | 0 | result += buffer.data(); // Using the C-string overload of string append. |
189 | 0 | } |
190 | 0 | } |
191 | 0 | return result; |
192 | 0 | } |
193 | | |
194 | | bool directoryExists(const std::string& dirPath) |
195 | 0 | { |
196 | 0 | struct stat info{}; |
197 | |
|
198 | 0 | if (stat(dirPath.c_str(), &info) != 0) |
199 | 0 | { |
200 | 0 | return false; |
201 | 0 | } |
202 | 0 | return (info.st_mode & S_IFDIR) != 0; |
203 | 0 | } |
204 | | |
205 | | int clockGetTime(long& sec, long& nsec) |
206 | 0 | { |
207 | 0 | using namespace std::chrono; |
208 | |
|
209 | 0 | auto now = system_clock::now(); |
210 | 0 | auto duration = now.time_since_epoch(); |
211 | |
|
212 | 0 | auto secondsDuration = duration_cast<seconds>(duration); |
213 | 0 | auto nanosecondsDuration = duration_cast<nanoseconds>(duration - secondsDuration); |
214 | |
|
215 | 0 | sec = static_cast<long>(secondsDuration.count()); |
216 | 0 | nsec = static_cast<long>(nanosecondsDuration.count()); |
217 | |
|
218 | 0 | return 0; |
219 | 0 | } |
220 | | |
221 | | time_t mkUtcTime(std::tm& time) |
222 | 70 | { |
223 | | #if defined(_WIN32) |
224 | | return _mkgmtime(&time); |
225 | | #else |
226 | 70 | return timegm(&time); |
227 | 70 | #endif |
228 | 70 | } |
229 | | |
230 | | void multiPlatformSleep(uint32_t seconds) |
231 | 0 | { |
232 | 0 | std::this_thread::sleep_for(std::chrono::seconds(seconds)); |
233 | 0 | } |
234 | | |
235 | | void multiPlatformMSleep(uint32_t milliseconds) |
236 | 0 | { |
237 | 0 | std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); |
238 | 0 | } |
239 | | |
240 | | uint16_t hostToNet16(uint16_t host) |
241 | 7.23k | { |
242 | 7.23k | return htobe16(host); |
243 | 7.23k | } |
244 | | |
245 | | uint16_t netToHost16(uint16_t net) |
246 | 14.4k | { |
247 | 14.4k | return be16toh(net); |
248 | 14.4k | } |
249 | | |
250 | | uint32_t hostToNet32(uint32_t host) |
251 | 7.23k | { |
252 | 7.23k | return htobe32(host); |
253 | 7.23k | } |
254 | | |
255 | | uint32_t netToHost32(uint32_t net) |
256 | 57.8k | { |
257 | 57.8k | return be32toh(net); |
258 | 57.8k | } |
259 | | |
260 | | std::string AppName::m_AppName; |
261 | | |
262 | | #if defined(_WIN32) |
263 | | int ApplicationEventHandler::handlerRoutine(unsigned long fdwCtrlType) |
264 | | { |
265 | | switch (fdwCtrlType) |
266 | | { |
267 | | case CTRL_C_EVENT: |
268 | | case CTRL_BREAK_EVENT: |
269 | | { |
270 | | if (ApplicationEventHandler::getInstance().m_ApplicationInterruptedHandler != nullptr) |
271 | | ApplicationEventHandler::getInstance().m_ApplicationInterruptedHandler( |
272 | | ApplicationEventHandler::getInstance().m_ApplicationInterruptedCookie); |
273 | | return TRUE; |
274 | | } |
275 | | |
276 | | default: |
277 | | return FALSE; |
278 | | } |
279 | | } |
280 | | #else |
281 | | |
282 | | static std::mutex UnixLinuxHandlerRoutineMutex; |
283 | | |
284 | | void ApplicationEventHandler::handlerRoutine(int signum) |
285 | 0 | { |
286 | 0 | switch (signum) |
287 | 0 | { |
288 | 0 | case SIGINT: |
289 | 0 | { |
290 | | // Most calls are unsafe in a signal handler, and this includes printf(). In particular, |
291 | | // if the signal is caught while inside printf() it may be called twice at the same time which might not be |
292 | | // a good idea The way to make sure the signal is called only once is using this lock and putting nullptr in |
293 | | // m_ApplicationInterruptedHandler |
294 | 0 | const std::lock_guard<std::mutex> lock(UnixLinuxHandlerRoutineMutex); |
295 | |
|
296 | 0 | if (ApplicationEventHandler::getInstance().m_ApplicationInterruptedHandler != nullptr) |
297 | 0 | { |
298 | 0 | ApplicationEventHandler::getInstance().m_ApplicationInterruptedHandler( |
299 | 0 | ApplicationEventHandler::getInstance().m_ApplicationInterruptedCookie); |
300 | 0 | } |
301 | |
|
302 | 0 | ApplicationEventHandler::getInstance().m_ApplicationInterruptedHandler = nullptr; |
303 | |
|
304 | 0 | return; |
305 | 0 | } |
306 | 0 | default: |
307 | 0 | { |
308 | 0 | return; |
309 | 0 | } |
310 | 0 | } |
311 | 0 | } |
312 | | #endif |
313 | | |
314 | | ApplicationEventHandler::ApplicationEventHandler() |
315 | 0 | : m_ApplicationInterruptedHandler(nullptr), m_ApplicationInterruptedCookie(nullptr) |
316 | 0 | {} |
317 | | |
318 | | void ApplicationEventHandler::onApplicationInterrupted(EventHandlerCallback handler, void* cookie) |
319 | 0 | { |
320 | 0 | m_ApplicationInterruptedHandler = handler; |
321 | 0 | m_ApplicationInterruptedCookie = cookie; |
322 | |
|
323 | | #if defined(_WIN32) |
324 | | SetConsoleCtrlHandler(reinterpret_cast<PHANDLER_ROUTINE>(handlerRoutine), TRUE); |
325 | | #else |
326 | 0 | struct sigaction action{}; |
327 | 0 | memset(&action, 0, sizeof(struct sigaction)); |
328 | 0 | action.sa_handler = handlerRoutine; |
329 | 0 | sigemptyset(&action.sa_mask); |
330 | | sigaction(SIGINT, &action, nullptr); |
331 | 0 | #endif |
332 | 0 | } |
333 | | |
334 | | } // namespace pcpp |