1. Overview
The USBScanPage.hpp header defines the USBScanPage class, a GTKmm (GTK4) UI component responsible for detecting USB storage devices, managing per-device scan state, mounting partitions when required, and executing antivirus scans (e.g., via clamdscan) in an asynchronous workflow. The page provides device cards, refresh controls, log visualization, and integration with a live scan dialog and DBus alerts for infected findings.
Functionally, USBScanPage provides:
- Discovery and display of connected USB storage devices
- Per-device lifecycle management (idle, mounting, scanning)
- Automatic or manual refresh of device inventory
- Partition mounting and mount point resolution
- Asynchronous scan execution and live output streaming
- Result reporting, including infected file dialogs
- Persistent logging and UI log view synchronization
- DBus alert emission for security events
2. Dependencies and Includes
#include <gtkmm.h>
#include <set>
#include <queue>
#include <thread>
#include <atomic>
#include <filesystem>
#include <unordered_map>
#include <mutex>
- gtkmm.h – GTK4 C++ widgets, signals, and UI primitives
- <set> – tracking of known devices (implementation-dependent usage)
- <queue> – queued work and output buffering patterns (implementation-dependent usage)
- <thread> – background monitoring and scan execution
- <atomic> – lock-free flags for monitor lifecycle and state control
- <filesystem> – filesystem operations and path handling
- <unordered_map> – per-device scan state mapping by stable UID
- <mutex> – synchronization for scan gating and log buffering
3. Data Structures
3.1 USB Device Information Model
struct USBDeviceInfo {
std::string name;
std::string devnode;
std::string serial;
std::string uid;
uint64_t size_bytes = 0;
};
Represents a detected USB storage device. The uid field is intended to be a stable cross-distribution identity used as the primary key for scan state management.
- name – user-friendly device name/model
- devnode – device node path (e.g.,
/dev/sdb1) - serial – device serial identifier, when available
- uid – stable device identity used for gating and state tracking
- size_bytes – device size for display and reporting
3.2 Scan State
enum class ScanState {
Idle,
Mounting,
Scanning
};
Encodes the per-device scan lifecycle state to prevent conflicting operations and to support clear UI messaging and safe concurrency.
4. Class Declaration and Scope
class USBScanPage : public Gtk::Box
The class derives from Gtk::Box, making it suitable as a page within a notebook or any container-based GTK layout.
5. Public Interface
5.1 Constructor
USBScanPage();
Initializes widgets, prepares logging and device views, and starts background monitoring as required by the page configuration.
5.2 Destructor
virtual ~USBScanPage() = default;
Uses default destruction semantics; thread shutdown and resource cleanup should be handled carefully by implementation to avoid detached worker lifetimes outliving the UI.
6. Device Discovery and UI Rendering
std::vector<USBDeviceInfo> detect_usb_devices();
void update_cards();
Gtk::Widget* build_usb_card(const USBDeviceInfo& dev);
- detect_usb_devices() – discovers connected USB devices and returns their metadata
- update_cards() – refreshes the UI to reflect the current device inventory
- build_usb_card() – constructs a visual device card widget for a single device
7. Mounting Utilities
std::string find_mountpoint(const std::string& devnode);
std::string mount_partition(const std::string& devnode, bool& auto_mounted);
- find_mountpoint() – resolves an existing mount point for a given device node
- mount_partition() – mounts the partition when needed and returns the mount path;
auto_mountedindicates whether the page performed the mount operation
8. Scanning Workflow
void run_clamdscan_async(const std::string& devnode);
bool try_start_scan(const std::string& uid);
void show_scan_result(const std::string& text);
void show_infected_dialog(const std::string& text);
std::string build_scan_report(const std::string& raw);
- run_clamdscan_async() – launches the antivirus scan asynchronously for the device
- try_start_scan() – absolute gating mechanism preventing concurrent scans per device UID
- show_scan_result() – displays the scan summary to the user
- show_infected_dialog() – displays a high-visibility alert for infected findings
- build_scan_report() – transforms raw scan output into a user-friendly report
9. Logging
void write_log(const std::string& msg);
void update_log_view();
std::string get_log_path();
Provides a persistent logging subsystem with buffered UI updates to keep the GTK main loop responsive. Logs are written to a resolved path returned by get_log_path() and displayed in txt_log_.
10. Monitor Thread
void start_monitor_thread();
Starts a background monitoring thread that detects device add/remove events and triggers UI refreshes. Monitor state is tracked via monitor_thread_ and monitor_running_.
11. Live Scan Output
void append_live_output(const std::string& line);
Streams scan output lines into a live scan dialog (if present), enabling real-time visibility into scan progress and findings.
12. DBus Alert Integration
void send_dbus_alert(const std::string& file,
const std::string& family);
Sends a DBus alert describing an infected file and its detected family. This allows integration with desktop notifications, system services, or centralized security event handling.
13. Widgets
Gtk::FlowBox flowbox_devices_;
Gtk::Button btn_refresh_;
Gtk::CheckButton chk_auto_refresh_;
Gtk::Label lbl_title_;
Gtk::Label lbl_status_;
Gtk::TextView txt_log_;
Gtk::ScrolledWindow scroller_log_;
- flowbox_devices_ – container for device cards
- btn_refresh_ – manual refresh of detected devices
- chk_auto_refresh_ – enables automatic refresh behavior
- lbl_title_ – page heading label
- lbl_status_ – status/diagnostic messages
- txt_log_ – text view displaying accumulated logs
- scroller_log_ – scrolled container for the log view
14. Threads and State Management
std::thread monitor_thread_;
std::atomic<bool> monitor_running_{false};
bool initial_scan_done_{false};
bool ignore_existing_devices_{true};
std::mutex scan_mtx_;
std::unordered_map<std::string, ScanState> device_state_;
- monitor_thread_ – background thread monitoring USB device changes
- monitor_running_ – lifecycle flag controlling the monitor loop
- initial_scan_done_ – indicates whether an initial baseline scan cycle has occurred
- ignore_existing_devices_ – policy flag controlling whether pre-existing devices are ignored
- scan_mtx_ – protects scan state transitions and gating
- device_state_ – per-device scan state map keyed by
uid
15. Logging Internals
std::mutex log_mtx_;
std::mutex pending_log_mtx_;
std::vector<std::string> pending_log_lines_;
sigc::connection log_idle_connection_;
sigc::connection auto_refresh_conn_;
The page uses buffered log lines and GTK idle/timer connections to update the UI efficiently and safely from background activity.
16. Live Scan Dialog Integration
class LiveScanDialog* live_scan_dialog_ = nullptr;
Gtk::TextView* live_scan_textview_ = nullptr;
Optional pointers to a live scan dialog and its output view, used to present real-time scanner output during active scans.
17. Helper Functions
static std::string human_readable_size(uint64_t bytes);
Converts a byte count into a user-friendly size string (e.g., KB/MB/GB) for display on device cards.
18. Runtime and Security Considerations
- Threading and GTK constraints: GTK widgets must be updated only on the main thread; background threads should communicate via idle handlers or dispatcher mechanisms
- Mount safety: mounting operations should validate device nodes, enforce safe mount options (e.g.,
nosuid,nodev,noexecwhere appropriate), and ensure cleanup on failure - Absolute scan gate:
try_start_scan()should prevent concurrent scans for the same device to avoid resource contention and inconsistent reporting - Privilege boundaries: device detection and mounting may require elevated permissions; UI should report permission failures clearly and safely
- Log integrity: logs should be stored with appropriate permissions and may require rotation to avoid unbounded growth
- DBus trust model: ensure DBus alerts do not leak sensitive file paths to untrusted listeners and that message formats are validated
- Input sanitization: device labels, mount points, and scanner output should be treated as untrusted text when displayed or logged