• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 13535848071

26 Feb 2025 03:22AM UTC coverage: 91.695% (-0.001%) from 91.696%
13535848071

push

github

web-flow
Merge pull request #4718 from randombit/jack/split-cpuid

Make cpuid module optional

95832 of 104512 relevant lines covered (91.69%)

11266034.88 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.94
/src/cli/utils.cpp
1
/*
2
* (C) 2009,2010,2014,2015 Jack Lloyd
3
* (C) 2017 René Korthaus, Rohde & Schwarz Cybersecurity
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include "cli.h"
9

10
#include <botan/version.h>
11
#include <botan/internal/stl_util.h>
12
#include <botan/internal/target_info.h>
13
#include <iomanip>
14
#include <sstream>
15

16
#if defined(BOTAN_HAS_CPUID)
17
   #include <botan/internal/cpuid.h>
18
#endif
19

20
#if defined(BOTAN_HAS_HTTP_UTIL)
21
   #include <botan/internal/http_util.h>
22
#endif
23

24
#if defined(BOTAN_HAS_UUID)
25
   #include <botan/uuid.h>
26
#endif
27

28
#if defined(BOTAN_HAS_OS_UTILS)
29
   #include <botan/internal/os_utils.h>
30
#endif
31

32
namespace Botan_CLI {
33

34
class Print_Help final : public Command {
35
   public:
36
      Print_Help() : Command("help") {}
4✔
37

38
      std::string help_text() const override {
1✔
39
         std::map<std::string, std::vector<std::unique_ptr<Command>>> grouped_commands;
1✔
40

41
         auto reg_commands = Command::registered_cmds();
1✔
42
         for(const auto& cmd_name : reg_commands) {
74✔
43
            auto cmd = Command::get_cmd(cmd_name);
73✔
44
            if(cmd) {
73✔
45
               grouped_commands[cmd->group()].push_back(std::move(cmd));
73✔
46
            }
47
         }
73✔
48

49
         const std::map<std::string, std::string> groups_description{{"codec", "Encoders/Decoders"},
1✔
50
                                                                     {"compression", "Compression"},
51
                                                                     {
52
                                                                        "crypto",
53
                                                                        "Encryption",
54
                                                                     },
55
                                                                     {"fec", "Forward Error Correction"},
56
                                                                     {"hash", "Hash Functions"},
57
                                                                     {"hmac", "HMAC"},
58
                                                                     {"info", "Informational"},
59
                                                                     {"misc", "Miscellaneous"},
60
                                                                     {"numtheory", "Number Theory"},
61
                                                                     {"passhash", "Password Hashing"},
62
                                                                     {"psk", "PSK Database"},
63
                                                                     {"pubkey", "Public Key Cryptography"},
64
                                                                     {"testing", "Testing"},
65
                                                                     {"tls", "TLS"},
66
                                                                     {"tss", "Secret Sharing"},
67
                                                                     {"x509", "X.509"}};
17✔
68

69
         std::ostringstream oss;
1✔
70

71
         oss << "Usage: botan <cmd> <cmd-options>\n";
1✔
72
         oss << "All commands support --verbose --help --output= --error-output= --rng-type= --drbg-seed=\n\n";
1✔
73
         oss << "Available commands:\n\n";
1✔
74

75
         for(const auto& commands : grouped_commands) {
19✔
76
            const std::string group = commands.first;
18✔
77
            if(group.empty()) {
18✔
78
               // ???
79
               continue;
1✔
80
            }
81

82
            auto descr = groups_description.find(group);
17✔
83
            if(descr != groups_description.end()) {
17✔
84
               oss << descr->second;
16✔
85
            } else {
86
               oss << group;
1✔
87
            }
88
            oss << ":\n";
17✔
89
            for(const auto& cmd : commands.second) {
89✔
90
               oss << "   " << std::setw(16) << std::left << cmd->cmd_name() << "   " << cmd->description() << "\n";
288✔
91
            }
92
            oss << "\n";
17✔
93
         }
18✔
94

95
         return oss.str();
1✔
96
      }
2✔
97

98
      std::string group() const override { return ""; }
1✔
99

100
      std::string description() const override { return "Prints a help string"; }
×
101

102
      void go() override {
1✔
103
         this->set_return_code(1);
1✔
104
         output() << help_text();
2✔
105
      }
1✔
106
};
107

108
BOTAN_REGISTER_COMMAND("help", Print_Help);
2✔
109

110
class Has_Command final : public Command {
111
   public:
112
      Has_Command() : Command("has_command cmd") {}
22✔
113

114
      std::string group() const override { return "info"; }
1✔
115

116
      std::string description() const override { return "Test if a command is available"; }
1✔
117

118
      void go() override {
10✔
119
         const std::string cmd = get_arg("cmd");
10✔
120

121
         bool exists = false;
10✔
122
         for(const auto& registered_cmd : Command::registered_cmds()) {
531✔
123
            if(cmd == registered_cmd) {
531✔
124
               exists = true;
125
               break;
126
            }
127
         }
10✔
128

129
         if(verbose()) {
10✔
130
            output() << "Command '" << cmd << "' is " << (exists ? "" : "not ") << "available\n";
×
131
         }
132

133
         if(exists == false) {
10✔
134
            this->set_return_code(1);
×
135
         }
136
      }
10✔
137
};
138

139
BOTAN_REGISTER_COMMAND("has_command", Has_Command);
11✔
140

141
class Config_Info final : public Command {
142
   public:
143
      Config_Info() : Command("config info_type") {}
10✔
144

145
      std::string help_text() const override {
×
146
         return "Usage: config info_type\n"
×
147
                "   prefix: Print install prefix\n"
148
                "   cflags: Print include params\n"
149
                "   ldflags: Print linker params\n"
150
                "   libs: Print libraries\n";
×
151
      }
152

153
      std::string group() const override { return "info"; }
1✔
154

155
      std::string description() const override { return "Print the used prefix, cflags, ldflags or libs"; }
1✔
156

157
      void go() override {
4✔
158
         const std::string arg = get_arg("info_type");
4✔
159

160
         if(arg == "prefix") {
4✔
161
            output() << BOTAN_INSTALL_PREFIX << "\n";
1✔
162
         } else if(arg == "cflags") {
3✔
163
            output() << "-I" << BOTAN_INSTALL_PREFIX << "/" << BOTAN_INSTALL_HEADER_DIR << "\n";
1✔
164
         } else if(arg == "ldflags") {
2✔
165
            if(*BOTAN_LINK_FLAGS) {
1✔
166
               output() << BOTAN_LINK_FLAGS << ' ';
1✔
167
            }
168
            output() << "-L" << BOTAN_INSTALL_LIB_DIR << "\n";
1✔
169
         } else if(arg == "libs") {
1✔
170
            output() << "-lbotan-" << Botan::version_major() << " " << BOTAN_LIB_LINK << "\n";
1✔
171
         } else {
172
            throw CLI_Usage_Error("Unknown option to botan config " + arg);
×
173
         }
174
      }
4✔
175
};
176

177
BOTAN_REGISTER_COMMAND("config", Config_Info);
5✔
178

179
class Version_Info final : public Command {
180
   public:
181
      Version_Info() : Command("version --full") {}
6✔
182

183
      std::string group() const override { return "info"; }
1✔
184

185
      std::string description() const override { return "Print version info"; }
1✔
186

187
      void go() override {
2✔
188
         if(flag_set("full")) {
2✔
189
            output() << Botan::version_string() << "\n";
3✔
190
         } else {
191
            output() << Botan::short_version_string() << "\n";
3✔
192
         }
193
      }
2✔
194
};
195

196
BOTAN_REGISTER_COMMAND("version", Version_Info);
3✔
197

198
#if defined(BOTAN_HAS_CPUID)
199

200
class Print_Cpuid final : public Command {
201
   public:
202
      Print_Cpuid() : Command("cpuid") {}
32✔
203

204
      std::string group() const override { return "info"; }
1✔
205

206
      std::string description() const override {
1✔
207
         return "List available processor flags (aes_ni, SIMD extensions, ...)";
1✔
208
      }
209

210
      void go() override { output() << "CPUID flags: " << Botan::CPUID::to_string() << "\n"; }
45✔
211
};
212

213
BOTAN_REGISTER_COMMAND("cpuid", Print_Cpuid);
16✔
214

215
#endif
216

217
#if defined(BOTAN_HAS_OS_UTILS)
218

219
class Cycle_Counter final : public Command {
220
   public:
221
      Cycle_Counter() : Command("cpu_clock --test-duration=500") {}
4✔
222

223
      std::string group() const override { return "info"; }
1✔
224

225
      std::string description() const override { return "Estimate the speed of the CPU cycle counter"; }
1✔
226

227
      void go() override {
1✔
228
         if(Botan::OS::get_cpu_cycle_counter() == 0) {
1✔
229
            output() << "No CPU cycle counter on this machine\n";
×
230
            return;
×
231
         }
232

233
         const uint64_t test_duration_ns = get_arg_sz("test-duration") * 1000000;
1✔
234

235
         if(test_duration_ns == 0) {
1✔
236
            output() << "Invalid test duration\n";
×
237
            return;
×
238
         }
239

240
         const uint64_t cc_start = Botan::OS::get_cpu_cycle_counter();
1✔
241
         const uint64_t ns_start = Botan::OS::get_system_timestamp_ns();
1✔
242

243
         uint64_t cc_end = 0;
1✔
244
         uint64_t ns_end = ns_start;
1✔
245

246
         while((ns_end - ns_start) < test_duration_ns) {
3,891,480✔
247
            ns_end = Botan::OS::get_system_timestamp_ns();
3,891,478✔
248
            cc_end = Botan::OS::get_cpu_cycle_counter();
3,891,478✔
249
         }
250

251
         if(cc_end <= cc_start) {
1✔
252
            output() << "Cycle counter seems to have wrapped, try again\n";
×
253
            return;
×
254
         }
255

256
         if(ns_end <= ns_start) {
1✔
257
            output() << "System clock seems to have wrapped (?!?)\n";
×
258
            return;
×
259
         }
260

261
         const uint64_t ns_duration = ns_end - ns_start;
1✔
262
         const uint64_t cc_duration = cc_end - cc_start;
1✔
263

264
         const double ratio = static_cast<double>(cc_duration) / ns_duration;
1✔
265

266
         if(ratio >= 1.0) {
1✔
267
            // GHz
268
            output() << "Estimated CPU clock " << std::setprecision(2) << ratio << " GHz\n";
1✔
269
         } else {
270
            // MHz
271
            output() << "Estimated CPU clock " << static_cast<size_t>(ratio * 1000) << " MHz\n";
×
272
         }
273
      }
274
};
275

276
BOTAN_REGISTER_COMMAND("cpu_clock", Cycle_Counter);
2✔
277

278
#endif
279

280
#if defined(BOTAN_HAS_UUID)
281

282
class Print_UUID final : public Command {
283
   public:
284
      Print_UUID() : Command("uuid") {}
6✔
285

286
      std::string group() const override { return "misc"; }
1✔
287

288
      std::string description() const override { return "Print a random UUID"; }
1✔
289

290
      void go() override {
2✔
291
         Botan::UUID uuid(rng());
2✔
292
         output() << uuid.to_string() << "\n";
6✔
293
      }
2✔
294
};
295

296
BOTAN_REGISTER_COMMAND("uuid", Print_UUID);
3✔
297

298
#endif
299

300
#if defined(BOTAN_HAS_HTTP_UTIL)
301

302
class HTTP_Get final : public Command {
303
   public:
304
      HTTP_Get() : Command("http_get --redirects=1 --timeout=3000 url") {}
2✔
305

306
      std::string group() const override { return "misc"; }
1✔
307

308
      std::string description() const override { return "Retrieve resource from the passed http/https url"; }
1✔
309

310
      void go() override {
×
311
         const std::string url = get_arg("url");
×
312
         const std::chrono::milliseconds timeout(get_arg_sz("timeout"));
×
313
         const size_t redirects = get_arg_sz("redirects");
×
314

315
         output() << Botan::HTTP::GET_sync(url, redirects, timeout) << "\n";
×
316
      }
×
317
};
318

319
BOTAN_REGISTER_COMMAND("http_get", HTTP_Get);
1✔
320

321
#endif  // http_util
322

323
}  // namespace Botan_CLI
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc