ClamdConfig.hpp

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 OnAccessIncludePath directives
  • 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 both options and rawLines
  • save() – writes current configuration state back to path
  • saveWithBackup() – saves configuration while creating a backup file first (documented as clamd.conf.bak or 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.conf locations 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.