USBScanPage.hpp

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_mounted indicates 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, noexec where 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