Coverage Report

Created: 2026-06-10 07:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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