1. Overview
The AppConsole class implements the command-line interface of BastionGuard Backup.
It translates terminal arguments and interactive user input into operations performed by the central Main controller. The class does not implement the snapshot engines directly; instead, it coordinates repository selection, snapshot creation, restoration, deletion, device mapping, GRUB configuration, and console output.
The supported command-line workflows include:
- Creating scheduled snapshots
- Creating on-demand snapshots
- Restoring an existing snapshot
- Deleting one snapshot
- Deleting all snapshots
- Listing available snapshots
- Listing Linux filesystem devices
- Selecting restore-target devices interactively
- Selecting the GRUB installation device
- Running in interactive or scripted mode
2. Class Definition
The class derives from GLib.Object:
public class AppConsole : GLib.Object
The class contains a static main() entry point and instance methods for executing the selected console operation.
3. Dependencies
The module imports:
using GLib;
using Gtk;
using Gee;
using Json;
It also integrates several TeeJee utility modules:
- TeeJee.Logging – console, debug, command, and error output
- TeeJee.FileSystem – filesystem and temporary-directory helpers
- TeeJee.JsonHelper – shared JSON utilities
- TeeJee.ProcessHelper – process and command integration
- TeeJee.GtkHelper – GTK event and message helpers
- TeeJee.System – device and administrator-account checks
- TeeJee.Misc – shared formatting and utility functions
The class directly interacts with:
- Main – central backup and restore controller
- SnapshotRepo – snapshot repository selection and status
- Snapshot – snapshot selection and deletion
- Device – block-device enumeration and resolution
- MountEntry – restore mount-point mappings
- TimeoutCounter – timeout handling for terminal input
4. Global Application State
The console module defines the shared application controller:
public Main App;
This global object is initialized after privilege checks and is used by all console methods.
The application identity constants are:
public const string AppName = "BastionGuard Backup";
public const string AppShortName = "bastionguard-backup";
public const string AppVersion = Constants.VERSION;
public const string AppAuthor = "Tony George";
public const string AppAuthorEmail = "teejeetech@gmail.com";
5. Localization Configuration
The gettext configuration is defined through:
const string GETTEXT_PACKAGE = "bastionguard-backup";
const string LOCALE_DIR = "/usr/share/locale";
5.1 set_locale()
private static void set_locale()
The method initializes the process locale and translation domain:
Intl.setlocale(GLib.LocaleCategory.ALL, "");
Intl.bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR);
Intl.bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
Intl.textdomain(GETTEXT_PACKAGE);
Console help, status messages, prompts, and errors can therefore be translated through gettext.
6. Console Pagination State
public int snapshot_list_start_index = 0;
This field stores the first snapshot index displayed by the interactive snapshot selector.
It is modified when the user requests the previous or next page.
7. Console Entry Point
7.1 main()
public static int main(string[] args)
The static entry point initializes and executes the complete command-line application.
The startup sequence is:
- Initialize localization
- Disable timestamp prefixes for initial console output
- Process
--helpand--version - Display help when no arguments are supplied
- Copy the graphical-session environment when required
- Initialize temporary application paths
- Verify administrator privileges
- Create the central
Maincontroller - Parse all command-line options
- Initialize the snapshot repository
- Create the
AppConsoleinstance - Dispatch the selected operation
- Exit through
Main.exit_app()
8. Help and Version Fast Paths
The following arguments are processed before administrator validation:
--help
-h
--version
When no operational argument is supplied, the application also displays the help message and returns successfully.
This allows ordinary users to inspect command syntax and version information without root privileges.
9. Temporary Environment Initialization
Before temporary files are initialized, logging is disabled:
LOG_ENABLE = false;
init_tmp();
LOG_ENABLE = true;
This prevents temporary initialization messages from appearing in normal command-line output.
10. Administrator Requirement
10.1 check_if_admin()
public static void check_if_admin()
Operational console commands require administrator privileges.
The method checks:
user_is_admin()
If the process is not running with sufficient privileges, the application displays:
Application needs admin access.
Please run the application as admin (using 'sudo' or 'su')
The process then terminates with exit status 1.
11. Main Controller Initialization
The central application object is created in non-GUI mode:
App = new Main(args, false);
After complete command-line parsing, repository initialization is performed through:
App.initialize();
The console layer then invokes:
console.start_application();
12. Command-Line Argument Parsing
12.1 parse_arguments()
private static void parse_arguments(string[] args)
The method processes all arguments beginning at index 1. Index 0 contains the executable path.
Each recognized option updates fields in the shared Main controller.
13. Snapshot Creation Options
The following options select snapshot-creation modes:
--check– create a snapshot only when a configured schedule is due--create– always create an on-demand snapshot
The corresponding application modes are:
backup
ondemand
Both modes disable timestamped and debug output by default.
14. Restore and Clone Options
The restore options are:
--restore– restore an existing snapshot--clone– use the restore engine to clone the current system
For ordinary restoration:
App.mirror_system = false;
App.app_mode = "restore";
For cloning:
App.mirror_system = true;
App.app_mode = "restore";
The clone option is accepted by the parser even though it is omitted from the generated help text.
15. Snapshot Deletion Options
The deletion modes are:
--delete– delete a selected snapshot--delete-all– delete every snapshot in the repository
The corresponding application modes are:
delete
delete-all
16. Listing Options
The console can display repository and device information through:
--list--list-snapshots--list-devices
The first two options select:
App.app_mode = "list-snapshots";
The device option selects:
App.app_mode = "list-devices";
17. Snapshot Metadata Options
User comments can be supplied with:
--comment <text>
--comments <text>
The value is stored in:
App.cmd_comments
Snapshot tags are supplied through:
--tags O,B,H,D,W,M
The value is stored in App.cmd_tags and validated immediately through:
App.validate_cmd_tags();
18. Restore Device Options
The following options specify restore-related devices:
--targetor--target-device– root restore target--grubor--grub-device– GRUB installation device--backup-deviceor--snapshot-device– snapshot repository device--snapshotor--snapshot-name– snapshot to restore or delete
The supplied values can later be resolved as:
- Device names
- Filesystem UUIDs
- Known device symbolic links
19. GRUB Options
The option:
--skip-grub
sets:
App.cmd_skip_grub = true;
Supplying a GRUB device enables bootloader reinstallation and stores the requested target:
App.reinstall_grub2 = true;
App.cmd_grub_device = <device>;
20. Output and Automation Options
The global output options are:
--verbose– display RSYNC output--quiet– suppress RSYNC output--debug– enable debug and command logging
Scripted execution is enabled through:
--scripted
This option also automatically confirms destructive prompts:
App.cmd_scripted = true;
App.cmd_confirm = true;
The option:
--yes
sets only the confirmation flag.
21. Snapshot Engine Overrides
The configured snapshot engine can be overridden through:
--btrfs--rsync
The parser updates both the active mode and the nullable command-line override:
App.btrfs_mode
App.cmd_btrfs_mode
22. Deprecated Options
The following legacy arguments are rejected:
--backup– replaced by--check--backup-now– replaced by--create
The parser displays an explanatory error and terminates through App.exit_app(1).
23. Invalid Arguments
Any unrecognized argument produces:
Invalid command line arguments: <argument>
The application mode is changed to:
abort
The process then exits with status 1.
24. Application Dispatch
24.1 start_application()
public bool start_application()
This method dispatches the operation selected by App.app_mode.
The supported dispatch targets are:
backup→ scheduled snapshot checkondemand→ forced snapshot creationrestore→ snapshot restoration or cloningdelete→ single-snapshot deletiondelete-all→ complete snapshot deletionlist-snapshots→ repository status and snapshot tablelist-devices→ Linux filesystem device table
25. Live-System Restrictions
Before dispatching an operation, the class checks:
App.live_system()
In a normal live environment, the following modes are rejected:
backup
ondemand
The console reports:
Snapshots cannot be created in Live CD mode
Recovery mode is handled by the central Main.live_system() logic and can bypass this restriction.
26. Version Output
26.1 version_message()
The version output uses:
<application-name> <version>
Example:
BastionGuard Backup 1.0.0
27. Help Output
27.1 help_message()
The generated help document contains:
- Application name and version
- Syntax summary
- Snapshot-listing options
- Backup options
- Restore options
- Deletion options
- Global options
- Examples
- Operational notes
The command syntax is based on:
bastionguard-backup
Example commands include:
bastionguard-backup --list
bastionguard-backup --create --comments "after update" --tags D
bastionguard-backup --restore --snapshot "2026-07-12_10-30-00" --target /dev/sda1
bastionguard-backup --delete --snapshot "2026-07-12_10-30-00"
bastionguard-backup --delete-all
28. Snapshot Table
28.1 list_snapshots()
private void list_snapshots(
bool paginate,
int page_size = 20
)
The method displays a table with the following columns:
Num
Name
Tags
Description
Each row displays:
- The repository-list index
- A selection marker
- The snapshot directory name
- The compact tag representation
- The user description
When pagination is enabled, only entries beginning at snapshot_list_start_index are displayed.
29. Device Tables
29.1 list_devices()
This method displays a supplied device collection using the columns:
Num
Device
Size
Type
Label
The displayed device name includes parent-device information when available.
29.2 list_all_devices()
The method enumerates devices through:
Device.get_block_devices_using_lsblk()
Only devices satisfying:
dev.has_linux_filesystem()
are included.
The resulting device collection is printed and returned for interactive selection.
30. GRUB Device Table
30.1 list_grub_devices()
The GRUB device list includes:
- Complete disk devices
- Partitions containing Linux filesystems
Encrypted mappings and loop devices are excluded.
The table displays:
Num
Device
Description
Disk descriptions can include vendor, model, and an [MBR] marker.
Partition descriptions include filesystem type, size, and optional label.
31. Grid Rendering
31.1 print_grid()
private void print_grid(
string[,] grid,
bool[] right_align,
bool has_header = true
)
The method provides reusable fixed-width terminal-table formatting.
Its processing steps are:
- Measure the maximum string length in each column
- Build left- or right-aligned format strings
- Print each row with two spaces between columns
- Print a 78-character separator after the header
32. Snapshot Creation
32.1 create_snapshot()
private bool create_snapshot(bool ondemand)
The console creation workflow:
- Selects or validates the snapshot repository device
- Calls the central snapshot-creation method
select_snapshot_device(false);
return App.create_snapshot(ondemand, null);
The parent GTK window is null because the operation runs from the terminal.
33. Restore Workflow
33.1 restore_snapshot()
The complete console restore workflow is:
- Select the snapshot repository device
- Select the snapshot to restore
- Display an interactive restore notice
- Initialize the target mount list
- Map target devices in RSYNC mode
- Select the GRUB device in RSYNC mode
- Request final confirmation
- Mount the target filesystems
- Delegate restoration to
Main.restore_snapshot()
BTRFS restoration skips the RSYNC device-mapping and GRUB-selection stages.
34. Interactive Restore Notice
Unless scripted mode is active, the user is informed that pressing Enter accepts default values for subsequent prompts.
The workflow pauses until the user presses Enter.
35. Snapshot Repository Device Selection
35.1 select_snapshot_device()
private void select_snapshot_device(bool prompt_if_empty)
Device selection is skipped during system cloning because the clone source is the active system.
Candidate devices are taken from App.partitions and filtered to Linux filesystems.
The user is prompted when:
- No repository device is currently available
- The operation requires snapshots and the current repository contains none
35.2 Scripted Device Failure
In scripted mode, missing or unavailable repository devices do not generate an interactive prompt.
The class reports either:
Snapshot device not selected
or:
Snapshot device not available
Device not found: UUID='...'
The application then exits with status 1.
35.3 Interactive Device Selection
The user can select a repository device by:
- Numeric list index
- Device path
- Pressing
ato abort
Input is attempted at most three times.
35.4 BTRFS Repository Validation
When BTRFS mode is enabled, the selected device is validated through:
App.check_device_for_backup(dev, true)
The device must represent a BTRFS system disk containing the root @ subvolume.
36. Snapshot Selection
36.1 select_snapshot()
The method selects a snapshot for restoration or deletion.
When --snapshot is supplied, the repository is searched for an exact snapshot-name match.
If no matching snapshot is found, the method reports an error.
36.2 Scripted Snapshot Selection
Scripted mode requires an explicit snapshot name:
--snapshot <name>
If it is omitted, the application exits with an error instead of prompting.
36.3 Interactive Snapshot Selection
Interactive selection supports:
- A numeric snapshot index
p– display the previous pagen– display the next pagea– abort
The user receives three attempts to provide a valid selection.
37. Restore and Delete Snapshot Assignment
The selected restore snapshot is assigned to:
App.snapshot_to_restore
The selected deletion snapshot is assigned to:
App.snapshot_to_delete
A null selection causes the application to terminate with an error.
38. Restore Mount Initialization
38.1 init_mounts()
The method delegates initial mount construction to:
App.init_mount_list();
Mount entries whose device remains null are then removed from the console restore list.
The remaining entries represent mount points that require an explicit target-device association.
39. Restore Device Mapping
39.1 map_devices()
The method maps restore mount points to target devices.
If --target-device is supplied, the requested root target is resolved by:
- Device path
- Filesystem UUID
- Known device symbolic link
A missing target device causes immediate termination.
39.2 Default Device Mapping
For every mount point, the default target depends on the operation:
- Clone mode: the selected root destination
- Normal restore: the original mapped device when available
- Fallback: the selected root destination
39.3 Current-System Restore
If the selected target root matches the active system root UUID, the device-mapping loop stops.
The existing system mount structure can then be reused by the restore engine.
39.4 Scripted Mapping
In scripted mode, each default device name must resolve successfully through:
Device.get_device_by_name(default_device)
A failed lookup terminates the operation.
39.5 Interactive Mapping
For each mount point, the user can:
- Press Enter to accept the default
- Enter
rto use the root device - Enter a device path
- Enter a numeric device index
- Enter
ato abort
The selected mapping is written to the corresponding MountEntry.
40. GRUB Device Selection
40.1 select_grub_device()
The method controls whether GRUB is reinstalled and selects its target device.
It begins by preserving the defaults generated by the central restore controller and resetting the active selection.
40.2 Command-Line GRUB Device
A supplied GRUB target is resolved against the GRUB-capable device list using:
- Device path
- Filesystem UUID
- Partition symbolic links
A missing device terminates the restore operation.
40.3 Clone Behavior
System cloning always enables GRUB reinstallation:
App.reinstall_grub2 = true;
40.4 Interactive Reinstallation Prompt
For an ordinary restore, the user may be asked:
Re-install GRUB2 bootloader? (y/n)
The default behavior is derived from the central controller’s distribution and restore-target analysis.
The --skip-grub option suppresses reinstallation.
40.5 GRUB Target Prompt
When GRUB reinstallation is enabled but no device has been selected, the class displays the GRUB device table.
The user can select:
- A numeric index
- A device path
- The default target by pressing Enter
ato abort
41. Restore Confirmation
41.1 confirm_restore()
If automatic confirmation is disabled, the class requests restore messages from:
App.get_restore_messages()
The messages describe:
- Devices and mount points that will be modified
- Reboot implications
- The restore disclaimer
The user must answer y to continue.
Entering n or a aborts the operation.
42. Terminal Input Timeout
All interactive input helpers create a TimeoutCounter:
var counter = new TimeoutCounter();
counter.exit_on_timeout();
After stdin.read_line() returns, the timeout counter is stopped.
This prevents unattended interactive operations from waiting indefinitely.
43. Generic Device Input
43.1 read_stdin_device()
The method accepts:
a– abort- An empty line – select the default device when available
- A path containing
/– resolve by device name - A number – resolve by list index
The values c and d are also treated as default-device requests.
44. Mount-Device Input
44.1 read_stdin_device_mounts()
This method handles target-device selection for a specific mount point.
Accepted values include:
- Empty input – keep the current mapping or use the clone root device
rorn– use the selected root targeta– abort- A device path
- A numeric index
45. Numeric Device Resolution
45.1 get_device_from_index()
The method parses the supplied text as an int64 and returns the device stored at the corresponding list position.
An invalid or out-of-range index returns null.
46. Snapshot Input and Pagination
46.1 read_stdin_snapshot()
The method handles interactive snapshot selection.
The pagination controls change snapshot_list_start_index in increments of ten:
p → -10
n → +10
The index is prevented from becoming negative or moving beyond the available snapshot count.
Snapshot names containing underscores or hyphens are currently rejected in the interactive reader. Selection is therefore performed by numeric index.
47. GRUB Confirmation Input
47.1 read_stdin_grub_install()
The accepted values are:
- Empty input – apply the recommended default
y– reinstall GRUBn– skip GRUB reinstallationa– abort
The method updates both:
App.reinstall_grub2
App.cmd_skip_grub
48. Restore Confirmation Input
48.1 read_stdin_restore_confirm()
The accepted values are:
y– enableApp.cmd_confirmn– aborta– abort
Empty or unknown input is rejected.
49. Single-Snapshot Deletion
49.1 delete_snapshot()
The deletion workflow is:
- Select the repository device
- Select the snapshot
- Invoke synchronous snapshot removal
App.snapshot_to_delete.remove(true);
The underlying Snapshot object selects the appropriate RSYNC or BTRFS deletion backend.
50. Complete Snapshot Deletion
50.1 delete_all_snapshots()
The method selects the repository device and iterates through every loaded snapshot:
foreach(var snap in App.repo.snapshots){
snap.remove(true);
}
Each deletion is performed synchronously.
51. Console Operation Flow
The complete runtime flow is:
- Parse the requested operation
- Initialize the main controller and repository
- Validate live-system restrictions
- Select required repository, snapshot, and target devices
- Collect interactive confirmation when necessary
- Delegate the operation to the main backup engine
- Perform centralized cleanup through
App.exit_app() - Return exit status
0on success or1on failure
52. Runtime and Security Considerations
- Administrator enforcement: operational commands require root or equivalent privileges.
- Non-interactive support: scripted mode prevents terminal prompts and enables confirmation automatically.
- Input timeouts: interactive reads are protected by
TimeoutCounter. - Device validation: target and repository devices are resolved against detected block-device information.
- BTRFS validation: BTRFS repositories must contain a supported system subvolume layout.
- Restore confirmation: destructive restore operations require explicit confirmation unless automation options are used.
- GRUB control: bootloader reinstallation can be accepted, skipped, or directed to a specific device.
- Live-environment protection: ordinary live systems cannot create snapshots.
- Centralized cleanup: application exit is delegated to
Main.exit_app(). - Translated interface: console messages use the configured gettext domain.
53. Implementation Considerations
- Argument bounds: options requiring a value use
args[++k]without checking whether another argument exists. - Global controller: the console relies on a mutable global
Appobject. - Hidden clone option:
--cloneis parsed but intentionally omitted from the help output. - Pagination mismatch:
list_snapshots()defaults to a page size of 20, while the previous and next controls move by 10 entries. - Unused parameter:
list_grub_devices()acceptsprint_to_consolebut does not use it. - Snapshot-name input: interactive selection does not currently support entering a snapshot name directly.
- Redundant variable: the command-line snapshot lookup declares a
foundflag that is never set because successful lookup returns immediately. - Normalized null input: several input methods replace a null line with an empty string, making later null checks redundant.
- Undocumented defaults: generic device input treats
canddas default selections even though the prompts do not describe these values. - Duplicate condition:
read_stdin_grub_install()contains two branches checking for null or empty input. - Deletion status:
delete_snapshot()ignores the Boolean result returned bySnapshot.remove()and always returnstrue. - Delete-all status:
delete_all_snapshots()ignores individual deletion failures and always returnstrue. - Repository refresh: deletion methods do not explicitly reload the repository after completing their loops.
- Empty-repository exit code: interactive snapshot selection exits with status
0when no snapshots are found. - Direct process exit: the administrator check calls the external
exit()function instead of centralized application cleanup. - Legacy author identity: help output continues to identify the original Timeshift author.
- GTK dependency: the command-line module imports GTK and processes GTK-compatible runtime behavior even though it does not create a normal GUI.
54. Licensing
The source file is distributed under the GNU General Public License, version 2 or, at the user’s option, any later version.
The original copyright notice identifies:
Copyright 2012-2018 Tony George
<teejeetech@gmail.com>
The software is provided without warranty, including implied warranties of merchantability or fitness for a particular purpose.
