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