Skip to content
API Documentation
BastionGuard™
device_enumerator.cpp
Go to the documentation of this file.
3
4#include <filesystem>
5#include <fstream>
6#include <sstream>
7#include <string>
8#include <vector>
9
10namespace fs = std::filesystem;
11
12namespace {
13 std::string trim(const std::string& s) {
14 const auto start = s.find_first_not_of(" \t\r\n");
15 if (start == std::string::npos) return "";
16 const auto end = s.find_last_not_of(" \t\r\n");
17 return s.substr(start, end - start + 1);
18 }
19
20 std::string read_text_file(const fs::path& p) {
21 std::ifstream f(p);
22 if (!f) return "";
23 std::ostringstream ss;
24 ss << f.rdbuf();
25 return trim(ss.str());
26 }
27
28 uint64_t read_u64_file(const fs::path& p) {
29 std::ifstream f(p);
30 uint64_t v = 0;
31 if (f) f >> v;
32 return v;
33 }
34
35 bool starts_with(const std::string& s, const std::string& prefix) {
36 return s.rfind(prefix, 0) == 0;
37 }
38
39 bool is_real_disk_name(const std::string& name) {
40 return starts_with(name, "sd") ||
41 starts_with(name, "nvme") ||
42 starts_with(name, "mmcblk") ||
43 starts_with(name, "vd") ||
44 starts_with(name, "hd") ||
45 starts_with(name, "md") ||
46 starts_with(name, "dm-") ||
47 starts_with(name, "loop");
48 }
49}
50
51std::vector<DeviceInfo> DeviceEnumerator::enumerate_linux_block_devices(bool include_health_probe) {
52 std::vector<DeviceInfo> out;
53 const fs::path sys_block{"/sys/block"};
54
55 if (!fs::exists(sys_block) || !fs::is_directory(sys_block)) {
56 return out;
57 }
58
59 for (const auto& entry : fs::directory_iterator(sys_block)) {
60 const auto name = entry.path().filename().string();
61 if (!is_real_disk_name(name)) {
62 continue;
63 }
64
65 DeviceInfo d;
66 d.name = name;
67 d.path = "/dev/" + name;
68 d.size_bytes = read_u64_file(entry.path() / "size") * 512ull;
69 d.model = read_text_file(entry.path() / "device/model");
70 d.transport = read_text_file(entry.path() / "device/subsystem" / "device" / "transport");
71 d.type = (starts_with(name, "loop") || starts_with(name, "dm-")) ? "virtual" : "disk";
72 d.removable = read_u64_file(entry.path() / "removable") != 0;
73
74 if (starts_with(name, "nvme")) {
75 d.transport = "NVMe";
76 } else if (starts_with(name, "md")) {
77 d.transport = "Linux RAID";
78 } else if (starts_with(name, "dm-")) {
79 d.transport = "Device Mapper";
80 } else if (starts_with(name, "loop")) {
81 d.transport = "Loop";
82 } else if (d.transport.empty()) {
83 d.transport = "Block";
84 }
85
86 if (include_health_probe) {
87 const auto health = DeviceHealthProbe::probe(d.path);
88 d.degraded = health.state != DeviceHealthState::Healthy;
89 d.health_summary = health.summary;
90 }
91
92 out.push_back(d);
93 }
94
95 return out;
96}
static std::vector< DeviceInfo > enumerate_linux_block_devices(bool include_health_probe=false)
static DeviceHealthReport probe(const std::string &device_path, CancelCallback cancel_cb={})
bool is_real_disk_name(const std::string &name)
std::string read_text_file(const fs::path &p)
std::string trim(const std::string &s)
bool starts_with(const std::string &s, const std::string &prefix)
std::string name
std::string health_summary
std::string model
std::string type
std::string transport
std::string path