1. Overview
The ClamdConfig.hpp header defines the ClamdConfig class, a configuration model and persistence layer for ClamAV daemon settings (typically clamd.conf) used by BastionGuard.
The component provides:
- Load/Save of configuration files while preserving raw line structure
- Safe persistence through backup creation prior to writes
- Typed accessors for boolean options (including handling of commented keys)
- On-access path management via
OnAccessIncludePathdirectives - Scan/alert option exposure as checkbox-friendly key/value flags
Internally, the class maintains both a normalized key/value map and a raw line representation, allowing it to round-trip configuration changes with minimal loss of formatting or comments.
2. Dependencies and Includes
#include <string>
#include <map>
#include <vector>
- <string> – keys, values, file paths
- <map> – normalized option storage
- <vector> – raw line storage and OnAccess paths lists
3. Core Responsibilities
- Parsing: load
clamd.conf-style key/value lines, preserving comments and original text for stable rewrites. - Normalization: expose a simplified API (
setOption/getOption) backed by an internal options map. - Boolean semantics: represent enable/disable states by both values and commenting behavior, consistent with common ClamAV configuration patterns.
- Safety: provide backup-on-save and explicit backup support for higher assurance persistence.
4. Public Interface
4.1 Construction
ClamdConfig() = default;
Uses default construction; all state is initialized to empty containers until load() is invoked.
4.2 Load and Save
bool load(const std::string& path);
bool save(const std::string& path);
bool saveWithBackup(const std::string& path);
- load() – reads and parses the configuration file at
path, populating bothoptionsandrawLines - save() – writes current configuration state back to
path - saveWithBackup() – saves configuration while creating a backup file first (documented as
clamd.conf.bakor equivalent naming policy)
Return value: all persistence methods return true on success and false on error.
4.3 Generic Option Accessors
void setOption(const std::string& key, const std::string& value);
std::string getOption(const std::string& key) const;
Provides generic key/value access to ClamAV configuration directives. The storage is backed by the internal options map.
Expected behavior: unknown keys typically return an empty string, a default value, or a sentinel depending on the implementation policy.
4.4 Boolean Option Semantics
bool getOptionBool(const std::string& key) const;
void setOptionBool(const std::string& key, bool enabled);
Boolean accessors interpret option state according to ClamAV configuration conventions:
- Enabled when the directive is present and not commented (and/or value is “yes/true/1”)
- Disabled when the directive is absent, explicitly disabled, or commented out
The normalization helper isYes() is used to interpret typical affirmative values.
4.5 On-Access Include Paths
std::vector<std::string> getOnAccessPaths() const;
void addOnAccessPath(const std::string& path);
void removeOnAccessPath(const std::string& path);
Manages the list of directories monitored by on-access scanning through OnAccessIncludePath-style directives.
- getOnAccessPaths() – returns the effective include paths
- addOnAccessPath() – appends a new include path (deduplication is implementation-defined)
- removeOnAccessPath() – removes a matching include path
4.6 Scan/Alert Options (Checkbox Model)
std::map<std::string, bool> getScanOptions() const;
void setScanOption(const std::string& key, bool enabled);
Exposes a checkbox-friendly representation of scan and alert options. This API is intended for UI grids of toggles where each option maps to a boolean state.
- getScanOptions() – returns all known scan-related options with enabled state
- setScanOption() – updates a scan option state, typically mirrored into raw lines
5. Internal Representation
5.1 Raw Line Model
struct Line {
std::string text;
std::string key;
std::string value;
bool commented = false;
};
Each parsed configuration line is represented with both its original text and its parsed components. This allows the save routine to preserve:
- Original line ordering
- Comments and commented-out directives
- Non-key/value lines (where supported by implementation)
5.2 Internal Containers
std::map<std::string, std::string> options;
std::vector<Line> rawLines;
- options – normalized key/value store for quick lookup and mutation
- rawLines – preserved representation for stable rewrite behavior
6. Internal Helpers
6.1 isYes()
static bool isYes(const std::string& v);
Parses affirmative values (e.g., “yes”, “true”, “1”) to support consistent boolean semantics.
6.2 backupFile()
bool backupFile(const std::string& path) const;
Creates a backup of the file at path before overwriting. This is used by saveWithBackup() to improve recoverability in case of partial writes or user misconfiguration.
7. Runtime and Safety Considerations
- Atomicity: for best results, saving should follow an atomic write pattern (temporary file + rename) to reduce corruption risk.
- Permissions:
clamd.conflocations are often system-owned; callers may need elevated privileges for writes. This class should remain policy-neutral and allow the caller (e.g., Settings module) to handle privilege boundaries. - Comment semantics: commenting/uncommenting directives is a common enable/disable mechanism; boolean getters/setters must keep the raw line model and normalized map consistent.
- Validation: path setters (e.g., on-access include paths) should validate input to avoid injecting invalid directives or unsafe/unintended scan scope.