Coverage Report

Created: 2025-07-11 07:47

/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