Skip to content
API Documentation
BastionGuard™
Main Class Reference
Inheritance diagram for Main:

Public Member Functions

 Main (string[] args, bool gui_mode)
void initialize ()
bool check_dependencies (out string msg)
void check_btrfs_version_capabilities ()
void check_and_remove_timeshift_btrfs ()
bool check_btrfs_layout_system (Gtk.Window? win=null)
bool check_btrfs_layout (Device? dev_root, Device? dev_home, bool unlock)
void add_default_exclude_entries ()
void add_app_exclude_entries ()
Gee.ArrayList< string > create_exclude_list_for_backup ()
Gee.ArrayList< string > create_exclude_list_for_restore ()
bool save_exclude_list_for_restore (string output_path)
void save_exclude_list_selections ()
bool live_system ()
bool create_snapshot (bool is_ondemand, Gtk.Window? parent_win)
void validate_cmd_tags ()
void delete_begin ()
void delete_thread ()
void init_mount_list ()
void init_boot_options ()
bool restore_snapshot (Gtk.Window? parent_win)
void get_restore_messages (bool formatted, out string msg_devices, out string msg_reboot, out string msg_disclaimer)
bool restore_execute_rsync ()
bool restore_execute_btrfs ()
bool create_pre_restore_snapshot_btrfs ()
void save_app_config ()
bool import_timeshift_config_if_available ()
void load_app_config ()
void set_first_run_flag ()
void initialize_repo ()
void update_partitions ()
void detect_system_devices ()
bool mount_target_devices (Gtk.Window? parent_win=null)
void unmount_target_device (bool exit_on_error=true)
bool unmount_device (string mount_point, bool exit_on_error=true)
SnapshotLocationStatus check_backup_location (out string message, out string details)
bool check_btrfs_volume (Device dev, string subvol_names, bool unlock)
void try_select_default_device_for_backup (Gtk.Window? parent_win)
bool check_device_for_backup (Device dev, bool unlock)
delegate void progressCallback ()
uint64 estimate_system_size (progressCallback? callback=null)
void query_subvolume_info (SnapshotRepo parent_repo)
void query_subvolume_info_thread ()
bool query_subvolume_ids ()
bool query_subvolume_id (string subvol_name)
bool query_subvolume_quotas ()
bool query_subvolume_quota (string subvol_name)
void cron_job_update ()
void clean_logs ()
void exit_app (int exit_code=0)

Static Public Member Functions

static void setup_env ()

Public Attributes

string app_path = ""
string share_folder = ""
string rsnapshot_conf_path = ""
string app_conf_path = ""
string app_conf_path_old = ""
string app_conf_path_default = ""
bool first_run = false
string backup_uuid = ""
string backup_parent_uuid = ""
bool btrfs_mode = true
bool include_btrfs_home_for_backup = false
bool include_btrfs_home_for_restore = false
bool stop_cron_emails = true
Gee.ArrayList< Device > partitions
Gee.ArrayList< string > exclude_list_user
Gee.ArrayList< string > exclude_list_default
Gee.ArrayList< string > exclude_list_default_extra
Gee.ArrayList< string > exclude_list_home
Gee.ArrayList< string > exclude_list_restore
Gee.ArrayList< AppExcludeEntry > exclude_list_apps
Gee.ArrayList< MountEntry > mount_list
Gee.ArrayList< string > exclude_app_names
SnapshotRepo repo
Device sys_root
Device sys_boot
Device sys_efi
Device sys_home
Gee.HashMap< string, Subvolume > sys_subvolumes
string mount_point_restore = ""
string mount_point_app = ""
LinuxDistro current_distro
bool mirror_system = false
bool schedule_monthly = false
bool schedule_weekly = false
bool schedule_daily = false
bool schedule_hourly = false
bool schedule_boot = false
int count_monthly = 2
int count_weekly = 3
int count_daily = 5
int count_hourly = 6
int count_boot = 5
string app_mode = ""
bool dry_run = false
bool thr_success = false
bool thread_restore_running = false
bool thread_restore_success = false
bool thread_delete_running = false
bool thread_delete_success = false
bool thread_subvol_info_running = false
bool thread_subvol_info_success = false
int thr_retval = -1
string thr_arg1 = ""
bool thr_timeout_active = false
string thr_timeout_cmd = ""
int startup_delay_interval_mins = 10
int retain_snapshots_max_days = 200
string log_dir = ""
string log_file = ""
AppLock app_lock
string date_format = "%Y-%m-%d %H:%M:%S"
Gee.ArrayList< Snapshot > delete_list
Snapshot snapshot_to_delete
Snapshot snapshot_to_restore
bool reinstall_grub2 = true
bool update_initramfs = false
bool update_grub = true
string grub_device = ""
bool use_option_raw = true
bool cmd_skip_grub = false
string cmd_grub_device = ""
string cmd_target_device = ""
string cmd_backup_device = ""
string cmd_snapshot = ""
bool cmd_confirm = false
bool cmd_verbose = true
bool cmd_scripted = false
string cmd_comments = ""
string cmd_tags = ""
bool? cmd_btrfs_mode = null
string progress_text = ""
Gtk.? Window parent_window = null
RsyncTask task
DeleteFileTask delete_file_task
RsyncSpaceCheckTask space_check_task
Gee.HashMap< string, SystemUser > current_system_users
string users_with_encrypted_home = ""
string encrypted_home_dirs = ""
bool encrypted_home_warning_shown = false
string encrypted_private_dirs = ""
bool encrypted_private_warning_shown = false

Static Public Attributes

static bool btrfs_version__can_recursive_delete = false
const uint64 MIN_FREE_SPACE = 1 * GB
static uint64 first_snapshot_size = 0
static int64 first_snapshot_count = 0
const string date_format_default = "%Y-%m-%d %H:%M:%S"

Protected Types

enum  QGroupStatus { UNKNOWN = -1 , DISABLED = 0 , ENABLED = 1 }

Properties

bool btrfs_qgroups_enabled [get]
bool scheduled [get]
Device? dst_root [get, set]
Device? dst_boot [get, set]
Device? dst_efi [get, set]
Device? dst_home [get, set]
bool restore_current_system [get]
string restore_source_path [get]
string restore_target_path [get]
string restore_log_file [get]
string restore_exclude_file [get]

Private Member Functions

int?[] get_btrfs_version_array ()
void parse_some_arguments (string[] args)
void detect_encrypted_dirs ()
void add_app_exclude_entries_for_prefix (string path_prefix)
string? save_exclude_list_for_backup (string output_path)
bool create_snapshot_for_tag (string tag, DateTime dt_created)
uint64 get_space_needed_for_rsync_snapshot (DateTime dt_created)
Snapshot? create_snapshot_with_rsync (string tag, DateTime dt_created)
Snapshot? create_snapshot_with_btrfs (string tag, DateTime dt_created)
void run_post_backup_hooks (string snapshot_path)
void set_tags (Snapshot snapshot)
void create_restore_scripts (out string sh_sync, out string sh_finish)
bool restore_current_console (string sh_sync, string sh_finish)
bool restore_current_gui (string sh_sync, string sh_finish)
bool restore_other_console (string sh_sync, string sh_finish)
bool restore_other_gui (string sh_sync, string sh_finish)
void fix_fstab_file (string target_path)
void fix_crypttab_file (string target_path)
void check_and_repair_filesystems ()
void cleanup_unmount_devices ()

Private Attributes

int _live_system = -1
QGroupStatus _btrfs_qgroups_enabled_internal = QGroupStatus.UNKNOWN

Detailed Description

Definition at line 39 of file Main.vala.

Member Enumeration Documentation

◆ QGroupStatus

enum Main.QGroupStatus
protected
Enumerator
UNKNOWN 
DISABLED 
ENABLED 

Definition at line 174 of file Main.vala.

174 {
175 UNKNOWN = -1,
176 DISABLED = 0,
177 ENABLED = 1
178 }

Constructor & Destructor Documentation

◆ Main()

Main.Main ( string[] args,
bool gui_mode )
inline

Definition at line 186 of file Main.vala.

186 {
187
188 this.mount_point_app = "/run/bastionguard-backup/%d".printf(Posix.getpid());
190
192
193 if (gui_mode){
194 app_mode = "";
195 parent_window = new Gtk.Window(); // dummy
196 }
197
198 log_debug("Main()");
199
200 if (LOG_DEBUG || gui_mode){
201 log_debug("");
202 log_debug(_("Running") + " %s v%s".printf(AppName, AppVersion));
203 log_debug("");
204 }
205
207
208 // init log ------------------
209
210 try {
211 string suffix = gui_mode ? "gui" : app_mode;
212
213 DateTime now = new DateTime.now_local();
214 log_dir = "/var/log/bastionguard-backup";
216 "%s_%s.log".printf(now.format("%Y-%m-%d_%H-%M-%S"), suffix));
217
218 var file = File.new_for_path (log_dir);
219 if (!file.query_exists ()) {
220 file.make_directory_with_parents();
221 }
222
223 file = File.new_for_path (log_file);
224 if (file.query_exists ()) {
225 file.delete ();
226 }
227
228 TeeJee.Logging.dos_log = new DataOutputStream (file.create(FileCreateFlags.REPLACE_DESTINATION));
229 if (LOG_DEBUG || gui_mode){
230 log_debug(_("Session log file") + ": %s".printf(log_file));
231 }
232 }
233 catch (Error e) {
234 log_error (e.message);
235 }
236
237 // get Linux distribution info -----------------------
238
239 this.current_distro = LinuxDistro.get_dist_info("/");
240
241 if (LOG_DEBUG || gui_mode){
242 log_debug(_("Distribution") + ": " + current_distro.full_name());
243 log_debug("DIST_ID" + ": " + current_distro.dist_id);
244 }
245
246 // check dependencies ---------------------
247
248 string message;
249 if (!check_dependencies(out message)){
250 if (gui_mode){
251 string title = _("Missing Dependencies");
252 gtk_messagebox(title, message, null, true);
253 }
254 exit_app(1);
255 }
256
258
259 // check and create lock ----------------------------
260
261 app_lock = new AppLock();
262
263 if (!app_lock.create("bastionguard-backup", app_mode)){
264 if (gui_mode){
265 // Show a polished, dedicated dialog explaining what is
266 // happening. Renders BEFORE MainWindow is constructed so
267 // the user is not confused by a half-built UI.
269 dlg.run_modal();
270 }
271 else{
272 //already logged - do nothing
273 }
274 exit(1);
275 }
276
277 // initialize variables -------------------------------
278
279 this.app_path = (File.new_for_path (args[0])).get_parent().get_path ();
280 this.share_folder = "/usr/share";
281 this.app_conf_path = "/etc/bastionguard-backup/bastionguard-backup.json";
282 this.app_conf_path_old = "/etc/bastionguard-backup.json";
283 this.app_conf_path_default = GLib.Path.build_path (GLib.Path.DIR_SEPARATOR_S, Constants.SYSCONFDIR, "bastionguard-backup", "default.json");
284 //sys_root and sys_home will be initialized by update_partition_list()
285
286 // check if running locally ------------------------
287
288 string local_exec = args[0];
289 string local_conf = app_path + "/bastionguard-backup.json";
290 string local_share = app_path + "/share";
291
292 var f_local_exec = File.new_for_path(local_exec);
293 if (f_local_exec.query_exists()){
294
295 var f_local_conf = File.new_for_path(local_conf);
296 if (f_local_conf.query_exists()){
297 this.app_conf_path = local_conf;
298 }
299
300 var f_local_share = File.new_for_path(local_share);
301 if (f_local_share.query_exists()){
302 this.share_folder = local_share;
303 }
304 }
305 else{
306 //bastionguard-backup is running from system directory - update app_path
307 this.app_path = Environment.find_program_in_path("bastionguard-backup");
308 }
309
310 // initialize lists -----------------
311
312 repo = new SnapshotRepo();
313 mount_list = new Gee.ArrayList<MountEntry>();
314 delete_list = new Gee.ArrayList<Snapshot>();
315 sys_subvolumes = new Gee.HashMap<string, Subvolume>();
316 exclude_app_names = new Gee.ArrayList<string>();
318 //add_app_exclude_entries();
319 task = new RsyncTask();
321
323
325
327
328 // set settings from config file ---------------------
329
331
332 IconManager.init(args, AppShortName);
333
334 log_debug("Main(): ok");
335 }
void exit(int exit_code)
#define _(s)
bool create(string app_name, string message)
Definition AppLock.vala:33
string lock_message
Definition AppLock.vala:31
BackupInProgressDialog(string lock_message)
string full_name()
string log_dir
Definition Main.vala:126
AppLock app_lock
Definition Main.vala:128
string log_file
Definition Main.vala:127
void check_and_remove_timeshift_btrfs()
Definition Main.vala:471
SnapshotRepo repo
Definition Main.vala:70
void parse_some_arguments(string[] args)
Definition Main.vala:537
RsyncTask task
Definition Main.vala:160
string app_mode
Definition Main.vala:98
void detect_encrypted_dirs()
Definition Main.vala:593
Gee.ArrayList< MountEntry > mount_list
Definition Main.vala:67
LinuxDistro current_distro
Definition Main.vala:84
Gtk.? Window parent_window
Definition Main.vala:158
void load_app_config()
Definition Main.vala:3564
void update_partitions()
Definition Main.vala:3819
Gee.ArrayList< string > exclude_app_names
Definition Main.vala:68
void detect_system_devices()
Definition Main.vala:3842
Gee.HashMap< string, Subvolume > sys_subvolumes
Definition Main.vala:79
Gee.ArrayList< Snapshot > delete_list
Definition Main.vala:133
void check_btrfs_version_capabilities()
Definition Main.vala:460
void add_default_exclude_entries()
Definition Main.vala:633
void exit_app(int exit_code=0)
Definition Main.vala:4574
string mount_point_app
Definition Main.vala:82
DeleteFileTask delete_file_task
Definition Main.vala:161
bool check_dependencies(out string msg)
Definition Main.vala:342
string app_path
Definition Main.vala:41
string path_combine(string path1, string path2)
bool dir_create(string dir_path, bool show_message=false)
void log_debug(string message)
void log_error(string message, bool highlight=false, bool is_warning=false)

References _, add_default_exclude_entries(), app_lock, app_mode, app_path, BackupInProgressDialog.BackupInProgressDialog(), check_and_remove_timeshift_btrfs(), check_btrfs_version_capabilities(), check_dependencies(), AppLock.create(), current_distro, delete_file_task, delete_list, DeleteFileTask.DeleteFileTask(), detect_encrypted_dirs(), detect_system_devices(), TeeJee.FileSystem.dir_create(), LinuxDistro.dist_id, TeeJee.Logging.dos_log, Error, exclude_app_names, exit(), exit_app(), LinuxDistro.full_name(), LinuxDistro.get_dist_info(), IconManager.init(), load_app_config(), AppLock.lock_message, TeeJee.Logging.LOG_DEBUG, TeeJee.Logging.log_debug(), log_dir, TeeJee.Logging.log_error(), log_file, mount_list, parent_window, parse_some_arguments(), TeeJee.FileSystem.path_combine(), repo, RsyncTask.RsyncTask(), sys_subvolumes, task, and update_partitions().

Referenced by create_snapshot_with_rsync(), delete_thread(), estimate_system_size(), get_space_needed_for_rsync_snapshot(), import_timeshift_config_if_available(), load_app_config(), AppConsole.main(), AppGtk.main(), and restore_other_gui().

Member Function Documentation

◆ add_app_exclude_entries()

void Main.add_app_exclude_entries ( )
inline

Definition at line 766 of file Main.vala.

766 {
767
768 log_debug("Main: add_app_exclude_entries()");
769
770 AppExcludeEntry.clear();
771
772 if (snapshot_to_restore != null){
774 }
775
776 //if (!restore_current_system){
777 // add_app_exclude_entries_for_prefix(mount_point_restore);
778 //}
779
780 exclude_list_apps = AppExcludeEntry.get_apps_list(exclude_app_names);
781
782 log_debug("Main: add_app_exclude_entries(): exit");
783 }
Snapshot snapshot_to_restore
Definition Main.vala:136
void add_app_exclude_entries_for_prefix(string path_prefix)
Definition Main.vala:785
Gee.ArrayList< AppExcludeEntry > exclude_list_apps
Definition Main.vala:66
string path
Definition Snapshot.vala:36

References add_app_exclude_entries_for_prefix(), AppExcludeEntry.clear(), exclude_app_names, exclude_list_apps, AppExcludeEntry.get_apps_list(), TeeJee.Logging.log_debug(), Snapshot.path, TeeJee.FileSystem.path_combine(), and snapshot_to_restore.

Referenced by RestoreWindow.validate_current_tab().

◆ add_app_exclude_entries_for_prefix()

void Main.add_app_exclude_entries_for_prefix ( string path_prefix)
inlineprivate

Definition at line 785 of file Main.vala.

785 {
786
787 string path = "";
788
789 path = path_combine(path_prefix, "root");
790 AppExcludeEntry.add_app_exclude_entries_from_path(path);
791
792 path = path_combine(path_prefix, "home");
793 AppExcludeEntry.add_app_exclude_entries_from_home(path);
794 }

References AppExcludeEntry.add_app_exclude_entries_from_home(), AppExcludeEntry.add_app_exclude_entries_from_path(), and TeeJee.FileSystem.path_combine().

Referenced by add_app_exclude_entries().

◆ add_default_exclude_entries()

void Main.add_default_exclude_entries ( )
inline

Definition at line 633 of file Main.vala.

633 {
634
635 log_debug("Main: add_default_exclude_entries()");
636
637 exclude_list_user = new Gee.ArrayList<string>();
638 exclude_list_default = new Gee.ArrayList<string>();
639 exclude_list_default_extra = new Gee.ArrayList<string>();
640 exclude_list_home = new Gee.ArrayList<string>();
641 exclude_list_restore = new Gee.ArrayList<string>();
642 exclude_list_apps = new Gee.ArrayList<AppExcludeEntry>();
643
644 partitions = new Gee.ArrayList<Device>();
645
646 // default exclude entries -------------------
647
648 exclude_list_default.add("/dev/*");
649 exclude_list_default.add("/proc/*");
650 exclude_list_default.add("/sys/*");
651 exclude_list_default.add("/media/*");
652 exclude_list_default.add("/mnt/*");
653 exclude_list_default.add("/tmp/*");
654 exclude_list_default.add("/run/*");
655 exclude_list_default.add("/var/run/*");
656 exclude_list_default.add("/var/lock/*");
657 //exclude_list_default.add("/var/spool/*");
658 exclude_list_default.add("/var/lib/dhcpcd/*");
659 exclude_list_default.add("/var/lib/docker/*");
660 exclude_list_default.add("/var/lib/schroot/*");
661 exclude_list_default.add("/lost+found");
662 exclude_list_default.add("/bastionguard-backup/*");
663 exclude_list_default.add("/bastionguard-backup-btrfs/*");
664 exclude_list_default.add("/data/*");
665 exclude_list_default.add("/DATA/*");
666 exclude_list_default.add("/cdrom/*");
667 exclude_list_default.add("/sdcard/*");
668 exclude_list_default.add("/system/*");
669 exclude_list_default.add("/etc/bastionguard-backup.json");
670 exclude_list_default.add("/var/log/bastionguard-backup/*");
671 exclude_list_default.add("/var/log/bastionguard-backup-btrfs/*");
672 exclude_list_default.add("/swapfile");
673 exclude_list_default.add("/snap/*");
674
675 foreach(var entry in FsTabEntry.read_file("/etc/fstab")){
676
677 if (!entry.mount_point.has_prefix("/")){ continue; }
678
679 // ignore standard system folders
680 if (entry.mount_point == "/"){ continue; }
681 if (entry.mount_point.has_prefix("/bin")){ continue; }
682 if (entry.mount_point.has_prefix("/boot")){ continue; }
683 if (entry.mount_point.has_prefix("/cdrom")){ continue; }
684 if (entry.mount_point.has_prefix("/dev")){ continue; }
685 if (entry.mount_point.has_prefix("/etc")){ continue; }
686 if (entry.mount_point.has_prefix("/home")){ continue; }
687 if (entry.mount_point.has_prefix("/lib")){ continue; }
688 if (entry.mount_point.has_prefix("/lib64")){ continue; }
689 if (entry.mount_point.has_prefix("/media")){ continue; }
690 if (entry.mount_point.has_prefix("/mnt")){ continue; }
691 if (entry.mount_point.has_prefix("/opt")){ continue; }
692 if (entry.mount_point.has_prefix("/proc")){ continue; }
693 if (entry.mount_point.has_prefix("/root")){ continue; }
694 if (entry.mount_point.has_prefix("/run")){ continue; }
695 if (entry.mount_point.has_prefix("/sbin")){ continue; }
696 if (entry.mount_point.has_prefix("/snap")){ continue; }
697 if (entry.mount_point.has_prefix("/srv")){ continue; }
698 if (entry.mount_point.has_prefix("/sys")){ continue; }
699 if (entry.mount_point.has_prefix("/system")){ continue; }
700 if (entry.mount_point.has_prefix("/tmp")){ continue; }
701 if (entry.mount_point.has_prefix("/usr")){ continue; }
702 if (entry.mount_point.has_prefix("/var")){ continue; }
703
704 // add exclude entry for devices mounted to non-standard locations
705
706 exclude_list_default_extra.add(entry.mount_point + "/*");
707 }
708
709 exclude_list_default.add("/root/.thumbnails");
710 exclude_list_default.add("/root/.cache");
711 exclude_list_default.add("/root/.dbus");
712 exclude_list_default.add("/root/.gvfs");
713 exclude_list_default.add("/root/.local/share/[Tt]rash");
714
715 exclude_list_default.add("/home/*/.thumbnails");
716 exclude_list_default.add("/home/*/.cache");
717 exclude_list_default.add("/home/*/.dbus");
718 exclude_list_default.add("/home/*/.gvfs");
719 exclude_list_default.add("/home/*/.local/share/[Tt]rash");
720
721 // default extra ------------------
722
723 exclude_list_default_extra.add("/root/.mozilla/firefox/*.default/Cache");
724 exclude_list_default_extra.add("/root/.mozilla/firefox/*.default/OfflineCache");
725 exclude_list_default_extra.add("/root/.opera/cache");
726 exclude_list_default_extra.add("/root/.kde/share/apps/kio_http/cache");
727 exclude_list_default_extra.add("/root/.kde/share/cache/http");
728
729 exclude_list_default_extra.add("/home/*/.mozilla/firefox/*.default/Cache");
730 exclude_list_default_extra.add("/home/*/.mozilla/firefox/*.default/OfflineCache");
731 exclude_list_default_extra.add("/home/*/.opera/cache");
732 exclude_list_default_extra.add("/home/*/.kde/share/apps/kio_http/cache");
733 exclude_list_default_extra.add("/home/*/.kde/share/cache/http");
734
735 exclude_list_default_extra.add("/var/cache/apt/archives/*");
736 exclude_list_default_extra.add("/var/cache/pacman/pkg/*");
737 exclude_list_default_extra.add("/var/cache/yum/*");
738 exclude_list_default_extra.add("/var/cache/dnf/*");
739 exclude_list_default_extra.add("/var/cache/eopkg/*");
740 exclude_list_default_extra.add("/var/cache/xbps/*");
741 exclude_list_default_extra.add("/var/cache/zypp/*");
742 exclude_list_default_extra.add("/var/cache/edb/*");
743
744 // default home ----------------
745
746 //exclude_list_home.add("+ /root/.**");
747 //exclude_list_home.add("+ /home/*/.**");
748 exclude_list_home.add("/root/**");
749 exclude_list_home.add("/home/*/**"); // Note: /home/** ignores include filters under /home
750
751 /*
752 Most web browsers store their cache under ~/.cache and /tmp
753 These files will be excluded by the entries for ~/.cache and /tmp
754 There is no need to add special entries.
755
756 ~/.cache/google-chrome -- Google Chrome
757 ~/.cache/chromium -- Chromium
758 ~/.cache/epiphany-browser -- Epiphany
759 ~/.cache/midori/web -- Midori
760 /var/tmp/kdecache-$USER/http -- Rekonq
761 */
762
763 log_debug("Main: add_default_exclude_entries(): exit");
764 }
Gee.ArrayList< string > exclude_list_restore
Definition Main.vala:65
Gee.ArrayList< string > exclude_list_default
Definition Main.vala:62
Gee.ArrayList< string > exclude_list_home
Definition Main.vala:64
Gee.ArrayList< Device > partitions
Definition Main.vala:59
Gee.ArrayList< string > exclude_list_user
Definition Main.vala:61
Gee.ArrayList< string > exclude_list_default_extra
Definition Main.vala:63

References exclude_list_apps, exclude_list_default, exclude_list_default_extra, exclude_list_home, exclude_list_restore, exclude_list_user, TeeJee.Logging.log_debug(), and partitions.

Referenced by Main().

◆ check_and_remove_timeshift_btrfs()

void Main.check_and_remove_timeshift_btrfs ( )
inline

Definition at line 471 of file Main.vala.

471 {
472
473 if (cmd_exists("bastionguard-backup-btrfs")){
474 string std_out, std_err;
475 exec_sync("bastionguard-backup-btrfs-uninstall", out std_out, out std_err);
476 log_msg(_("** Uninstalled BastionGuard Backup BTRFS **"));
477 }
478 }
void log_msg(string message, bool highlight=false)
int exec_sync(string cmd, out string? std_out=null, out string? std_err=null)

References _, TeeJee.ProcessHelper.exec_sync(), and TeeJee.Logging.log_msg().

Referenced by Main().

◆ check_and_repair_filesystems()

void Main.check_and_repair_filesystems ( )
inlineprivate

Definition at line 3051 of file Main.vala.

3051 {
3052
3054 string sh_fsck = "echo '" + _("Checking file systems for errors...") + "' \n";
3055 foreach(var mnt in mount_list){
3056 if (mnt.device != null) {
3057 sh_fsck += "fsck -y %s \n".printf(mnt.device.device);
3058 }
3059 }
3060 sh_fsck += "echo '' \n";
3061 exec_script_sync(sh_fsck, null, null, false, false, false, true);
3062 }
3063 }
bool restore_current_system
Definition Main.vala:2024
int exec_script_sync(string script, out string? std_out=null, out string? std_err=null, bool supress_errors=false, bool run_as_admin=false, bool cleanup_tmp=true, bool print_to_terminal=false)

References _, TeeJee.ProcessHelper.exec_script_sync(), mount_list, and restore_current_system.

Referenced by restore_execute_rsync().

◆ check_backup_location()

SnapshotLocationStatus Main.check_backup_location ( out string message,
out string details )
inline

Definition at line 4049 of file Main.vala.

4049 {
4051 message = repo.status_message;
4052 details = repo.status_details;
4053 return repo.status_code;
4054 }
string status_details
string status_message
SnapshotLocationStatus status_code

References SnapshotRepo.check_status(), repo, SnapshotRepo.status_code, SnapshotRepo.status_details, and SnapshotRepo.status_message.

◆ check_btrfs_layout()

bool Main.check_btrfs_layout ( Device? dev_root,
Device? dev_home,
bool unlock )
inline

Definition at line 507 of file Main.vala.

507 {
508
509 bool supported = true; // keep true for non-btrfs systems
510
511 if ((dev_root != null) && (dev_root.fstype == "btrfs")){
512
513 if ((dev_home != null) && (dev_home.fstype == "btrfs")){
514
515 if (dev_home != dev_root){
516
517 supported = supported && check_btrfs_volume(dev_root, "@", unlock);
518
520 supported = supported && check_btrfs_volume(dev_home, "@home", unlock);
521 }
522 }
523 else{
525 supported = supported && check_btrfs_volume(dev_root, "@,@home", unlock);
526 }
527 else{
528 supported = supported && check_btrfs_volume(dev_root, "@", unlock);
529 }
530 }
531 }
532 }
533
534 return supported;
535 }
bool check_btrfs_volume(Device dev, string subvol_names, bool unlock)
Definition Main.vala:4056
bool include_btrfs_home_for_backup
Definition Main.vala:53

References check_btrfs_volume(), Device.fstype, and include_btrfs_home_for_backup.

Referenced by RestoreDeviceBox.check_and_mount_devices(), and mount_target_devices().

◆ check_btrfs_layout_system()

bool Main.check_btrfs_layout_system ( Gtk.Window? win = null)
inline

Definition at line 480 of file Main.vala.

480 {
481
482 log_debug("check_btrfs_layout_system()");
483
484 bool supported = sys_subvolumes.has_key("@");
486 supported = supported && sys_subvolumes.has_key("@home");
487 }
488
489 if (!supported){
490 string msg = _("The system partition has an unsupported subvolume layout.") + " ";
491 msg += _("Only ubuntu-type layouts with @ and @home subvolumes are currently supported.") + "\n\n";
492 msg += _("Application will exit.") + "\n\n";
493 string title = _("Not Supported");
494
495 if (app_mode == ""){
496 gtk_set_busy(false, win);
497 gtk_messagebox(title, msg, win, true);
498 }
499 else{
500 log_error(msg);
501 }
502 }
503
504 return supported;
505 }
void gtk_set_busy(bool busy, Gtk.Window win)

References _, app_mode, TeeJee.GtkHelper.gtk_set_busy(), include_btrfs_home_for_backup, TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), and sys_subvolumes.

Referenced by create_snapshot(), and MainWindow.create_snapshot().

◆ check_btrfs_version_capabilities()

void Main.check_btrfs_version_capabilities ( )
inline

Definition at line 460 of file Main.vala.

460 {
461 var version = get_btrfs_version_array();
462
463 if (version != null) {
464 btrfs_version__can_recursive_delete = version[0] > 6 || (version[0] == 6 && version[1] >= 12);
465 log_debug("-- btrfs-progs version %d.%d.x".printf(version[0], version[1]));
466 }
467
468 log_debug("-- btrfs subvolume recursive delete: %s".printf(btrfs_version__can_recursive_delete ? "supported" : "not supported"));
469 }
int?[] get_btrfs_version_array()
Definition Main.vala:392
static bool btrfs_version__can_recursive_delete
Definition Main.vala:55

References btrfs_version__can_recursive_delete, get_btrfs_version_array(), and TeeJee.Logging.log_debug().

Referenced by Main().

◆ check_btrfs_volume()

bool Main.check_btrfs_volume ( Device dev,
string subvol_names,
bool unlock )
inline

Definition at line 4056 of file Main.vala.

4056 {
4057
4058 log_debug("check_btrfs_volume():%s".printf(subvol_names));
4059
4060 string mnt_btrfs = mount_point_app + "/btrfs";
4061 dir_create(mnt_btrfs);
4062
4063 if (!dev.is_mounted_at_path("", mnt_btrfs)){
4064
4065 Device.unmount(mnt_btrfs);
4066
4067 // unlock encrypted device
4068 if (dev.is_encrypted_partition()){
4069
4070 if (unlock){
4071
4072 string msg_out, msg_err;
4073 var dev_unlocked = Device.luks_unlock(
4074 dev, "", "", parent_window, out msg_out, out msg_err);
4075
4076 if (dev_unlocked == null){
4077 log_debug("device is null");
4078 log_debug("SnapshotRepo: check_btrfs_volume(): exit");
4079 return false;
4080 }
4081 else{
4082 Device.mount(dev_unlocked.uuid, mnt_btrfs, "subvolid=0", true);
4083 }
4084 }
4085 else{
4086 return false;
4087 }
4088 }
4089 else{
4090 Device.mount(dev.uuid, mnt_btrfs, "subvolid=0", true);
4091 }
4092 }
4093
4094 bool supported = true;
4095
4096 foreach(string subvol_name in subvol_names.split(",")){
4097 supported = supported && dir_exists(path_combine(mnt_btrfs,subvol_name));
4098 }
4099
4100 if (Device.unmount(mnt_btrfs)){
4101 if (dir_exists(mnt_btrfs) && dir_is_empty(mnt_btrfs)){
4102 dir_delete(mnt_btrfs);
4103 log_debug(_("Removed mount directory: '%s'").printf(mnt_btrfs));
4104 }
4105 }
4106
4107 return supported;
4108 }
string uuid
Definition Device.vala:50
bool is_encrypted_partition()
Definition Device.vala:216
bool is_mounted_at_path(string subvolname, string mount_path)
Definition Device.vala:158
bool dir_is_empty(string dir_path)
bool dir_exists(string dir_path)

References _, TeeJee.FileSystem.dir_create(), TeeJee.FileSystem.dir_exists(), TeeJee.FileSystem.dir_is_empty(), Device.is_encrypted_partition(), Device.is_mounted_at_path(), TeeJee.Logging.log_debug(), Device.luks_unlock(), Device.mount(), mount_point_app, parent_window, TeeJee.FileSystem.path_combine(), Device.unmount(), and Device.uuid.

Referenced by check_btrfs_layout(), and check_device_for_backup().

◆ check_dependencies()

bool Main.check_dependencies ( out string msg)
inline

Definition at line 342 of file Main.vala.

342 {
343 log_debug("Main: check_dependencies()");
344
345 string[] dependencies = { "rsync","/sbin/blkid","df","mount","umount","fuser","crontab","cp","rm","touch","ln","sync", "run-parts"}; //"shutdown","chroot",
346
347 msg = "";
348 foreach(string cmd_tool in dependencies){
349 if(!cmd_exists(cmd_tool)) {
350 msg += " * " + cmd_tool + "\n";
351 }
352 }
353
354 if (msg.length > 0){
355 msg = _("Commands listed below are not available on this system") + ":\n\n" + msg + "\n";
356 msg += _("Please install required packages and try running TimeShift again");
357 log_error(msg);
358 return false;
359 }
360 else{
361 return true;
362 }
363 }

References _, TeeJee.Logging.log_debug(), and TeeJee.Logging.log_error().

Referenced by Main().

◆ check_device_for_backup()

bool Main.check_device_for_backup ( Device dev,
bool unlock )
inline

Definition at line 4148 of file Main.vala.

4148 {
4149 bool ok = false;
4150
4151 if (dev.type == "disk") { return false; }
4152 if (dev.has_children()) { return false; }
4153
4154 if (btrfs_mode && ((dev.fstype == "btrfs")||(dev.fstype == "luks"))){
4155 if (check_btrfs_volume(dev, "@", unlock)){
4156 return true;
4157 }
4158 }
4159 else if (!btrfs_mode && dev.has_linux_filesystem()){
4160 // TODO: check free space
4161 return true;
4162 }
4163
4164 return ok;
4165 }
string type
Definition Device.vala:64
bool has_linux_filesystem()
Definition Device.vala:191
bool has_children()
Definition Device.vala:228
string fstype
Definition Device.vala:65
bool btrfs_mode
Definition Main.vala:52

References btrfs_mode, check_btrfs_volume(), Device.fstype, Device.has_children(), Device.has_linux_filesystem(), and Device.type.

Referenced by AppConsole.select_snapshot_device(), and try_select_default_device_for_backup().

◆ clean_logs()

void Main.clean_logs ( )
inline

Definition at line 4523 of file Main.vala.

4523 {
4524
4525 log_debug("clean_logs()");
4526
4527 Gee.ArrayList<string> list = new Gee.ArrayList<string>();
4528
4529 try{
4530 var dir = File.new_for_path (log_dir);
4531 var enumerator = dir.enumerate_children ("*", 0);
4532
4533 var info = enumerator.next_file ();
4534 string path;
4535
4536 while (info != null) {
4537 if (info.get_file_type() == FileType.REGULAR) {
4538 path = log_dir + "/" + info.get_name();
4539 if (path != log_file) {
4540 list.add(path);
4541 }
4542 }
4543 info = enumerator.next_file ();
4544 }
4545
4546 CompareDataFunc<string> compare_func = (a, b) => {
4547 return strcmp(a,b);
4548 };
4549
4550 list.sort((owned) compare_func);
4551
4552 if (list.size > 500){
4553
4554 // delete oldest 100 files ---------------
4555
4556 for(int k = 0; k < 100; k++){
4557
4558 var file = File.new_for_path (list[k]);
4559
4560 if (file.query_exists()){
4561 file.delete();
4562 log_msg("%s: %s".printf(_("Removed"), list[k]));
4563 }
4564 }
4565
4566 log_msg(_("Older log files removed"));
4567 }
4568 }
4569 catch(Error e){
4570 log_error (e.message);
4571 }
4572 }

References _, Error, TeeJee.Logging.log_debug(), log_dir, TeeJee.Logging.log_error(), log_file, and TeeJee.Logging.log_msg().

Referenced by exit_app().

◆ cleanup_unmount_devices()

void Main.cleanup_unmount_devices ( )
inlineprivate

Definition at line 4600 of file Main.vala.

4600 {
4601
4602 log_debug("cleanup_unmount_devices()");
4603
4604 if (!dir_exists("/run/bastionguard-backup")){ return; }
4605
4606 var dirlist = dir_list_names("/run/bastionguard-backup");
4607
4608 foreach(var dname in dirlist){
4609
4610 int pid = int.parse(dname);
4611
4612 if (pid != Posix.getpid()){ // if some other process
4613
4614 // check if the process is still running
4615
4616 string procdir = "/proc/%d".printf(pid);
4617
4618 if (dir_exists(procdir)){ continue; }
4619 }
4620
4621 // -----------------------------------------------
4622
4623 string mdir = "/run/bastionguard-backup/%s".printf(dname);
4624
4625 var dirlist2 = dir_list_names(mdir);
4626
4627 foreach(var dname2 in dirlist2){
4628
4629 string mdir2 = "/run/bastionguard-backup/%s/%s".printf(dname, dname2);
4630
4631 // check if a device is mounted here
4632
4633 foreach (var dev in Device.get_filesystems()){
4634
4635 foreach (var mnt in dev.mount_points){
4636
4637 if (mnt.mount_point == mdir2){
4638
4639 log_debug("\nFound stale mount for device '%s' at path '%s'".printf(dev.device, mdir2));
4640
4641 string cmd = "umount '%s'".printf(escape_single_quote(mdir2));
4642 int retval = exec_sync(cmd);
4643
4644 if (retval != 0){
4645 log_debug("E: Failed to unmount");
4646 log_debug("Ret=%d".printf(retval));
4647 //ignore
4648 }
4649 else{
4650 log_debug("Unmounted successfully");
4651 }
4652
4653 // delete directory
4654 if(!dir_empty_delete(mdir2)) {
4655 log_debug("E: Failed to delete %s".printf(mdir2));
4656 }
4657 }
4658 }
4659 }
4660 }
4661
4662 if (dir_exists(mdir)){
4663
4664 string cmd3 = "rmdir '%s'".printf(escape_single_quote(mdir));
4665 int retval3 = exec_sync(cmd3);
4666
4667 if (retval3 != 0){
4668 log_error("Failed to remove directory");
4669 log_msg("Ret=%d".printf(retval3));
4670 //ignore
4671 }
4672 }
4673 }
4674 }
Gee.ArrayList< string > dir_list_names(string path)
string escape_single_quote(string file_path)

References TeeJee.FileSystem.dir_exists(), TeeJee.FileSystem.dir_list_names(), TeeJee.FileSystem.escape_single_quote(), TeeJee.ProcessHelper.exec_sync(), Device.get_filesystems(), TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), and TeeJee.Logging.log_msg().

Referenced by exit_app().

◆ create_exclude_list_for_backup()

Gee.ArrayList< string > Main.create_exclude_list_for_backup ( )
inline

Definition at line 797 of file Main.vala.

797 {
798
799 log_debug("Main: create_exclude_list_for_backup()");
800
801 var list = new Gee.ArrayList<string>();
802
803 // add user entries from current setting
804 // user entry is first since rsync prioritizes the first
805 // inclusion/exclusion patterns seen
806 // -------------------------------------------------------
807
808 foreach(string path in exclude_list_user){
809 if (!list.contains(path)){
810 list.add(path);
811 }
812 }
813
814 // add default entries ---------------------------
815
816 foreach(string path in exclude_list_default){
817 if (!list.contains(path)){
818 list.add(path);
819 }
820 }
821
822 // add default extra entries ---------------------------
823
824 foreach(string path in exclude_list_default_extra){
825 if (!list.contains(path)){
826 list.add(path);
827 }
828 }
829
830 // add entries to exclude **decrypted** contents in $HOME
831 // decrypted contents should never be backed-up or restored
832 // this overrides all other user entries in exclude_list_user
833 // -------------------------------------------------------
834
835 foreach(var user in current_system_users.values){
836
837 if (user.is_system){ continue; }
838
839 if (user.has_encrypted_home){
840
841 // exclude decrypted contents in user's home ($HOME)
842 string path = "%s/**".printf(user.home_path);
843 list.add(path);
844 }
845
846 if (user.has_encrypted_private_dirs){
847
848 foreach(string enc_path in user.encrypted_private_dirs){
849
850 // exclude decrypted contents in private dirs ($HOME/Private)
851 string path = "%s/**".printf(enc_path);
852 list.add(path);
853 }
854 }
855 }
856
857 // exclude each user individually if not included in exclude_list_user
858
859 foreach(var user in current_system_users.values){
860
861 if (user.is_system){ continue; }
862
863 string exc_pattern = "%s/**".printf(user.home_path);
864 string inc_pattern = "+ %s/**".printf(user.home_path);
865 string inc_hidden_pattern = "+ %s/.**".printf(user.home_path);
866
867 if (user.has_encrypted_home){
868 inc_pattern = "+ /home/.ecryptfs/%s/***".printf(user.name);
869 exc_pattern = "/home/.ecryptfs/%s/***".printf(user.name);
870 }
871
872 bool include_hidden = exclude_list_user.contains(inc_hidden_pattern);
873 bool include_all = exclude_list_user.contains(inc_pattern);
874 bool exclude_all = !include_hidden && !include_all;
875
876 if (exclude_all){
877 if (!exclude_list_user.contains(exc_pattern)){
878 exclude_list_user.add(exc_pattern);
879 }
880 if (exclude_list_user.contains(inc_pattern)){
881 exclude_list_user.remove(inc_pattern);
882 }
883 if (exclude_list_user.contains(inc_hidden_pattern)){
884 exclude_list_user.remove(inc_hidden_pattern);
885 }
886 }
887 }
888
889 // add common entries for excluding home folders for all users --------
890
891 foreach(string path in exclude_list_home){
892 if (!list.contains(path)){
893 list.add(path);
894 }
895 }
896
897 string timeshift_path = "/bastionguard-backup/*";
898 if (!list.contains(timeshift_path)){
899 list.add(timeshift_path);
900 }
901
902 log_debug("Main: create_exclude_list_for_backup(): exit");
903
904 return list;
905 }
Gee.HashMap< string, SystemUser > current_system_users
Definition Main.vala:164

References current_system_users, exclude_list_default, exclude_list_default_extra, exclude_list_home, exclude_list_user, and TeeJee.Logging.log_debug().

Referenced by ExcludeListSummaryWindow.refresh(), and save_exclude_list_for_backup().

◆ create_exclude_list_for_restore()

Gee.ArrayList< string > Main.create_exclude_list_for_restore ( )
inline

Definition at line 907 of file Main.vala.

907 {
908
909 log_debug("Main: create_exclude_list_for_restore()");
910
911 exclude_list_restore.clear();
912
913 //add user entries from current settings
914 //user entry is first since rsync prioritizes the first
915 //inclusion/exclusion patterns seen
916 foreach(string path in exclude_list_user){
917
918 // skip include filters for restore
919 if (path.strip().has_prefix("+")){ continue; }
920
921 if (!exclude_list_restore.contains(path) && !exclude_list_home.contains(path)){
922 exclude_list_restore.add(path);
923 }
924 }
925
926 //add user entries from snapshot exclude list
927 if (snapshot_to_restore != null){
928 string list_file = path_combine(snapshot_to_restore.path, "exclude.list");
929 if (file_exists(list_file)){
930 foreach(string path in file_read(list_file).split("\n")){
931 if (!exclude_list_restore.contains(path) && !exclude_list_home.contains(path)){
932 exclude_list_restore.add(path);
933 }
934 }
935 }
936 }
937
938 //add default entries
939 foreach(string path in exclude_list_default){
940 if (!exclude_list_restore.contains(path)){
941 exclude_list_restore.add(path);
942 }
943 }
944
945 if (!mirror_system){
946 //add default_extra entries
947 foreach(string path in exclude_list_default_extra){
948 if (!exclude_list_restore.contains(path)){
949 exclude_list_restore.add(path);
950 }
951 }
952 }
953
954 //add app entries
955 foreach(var entry in exclude_list_apps){
956 if (entry.enabled){
957 foreach(var pattern in entry.patterns){
958 if (!exclude_list_restore.contains(pattern)){
959 exclude_list_restore.add(pattern);
960 }
961 }
962 }
963 }
964
965 //add home entries
966 foreach(string path in exclude_list_home){
967 if (!exclude_list_restore.contains(path)){
968 exclude_list_restore.add(path);
969 }
970 }
971
972 string timeshift_path = "/bastionguard-backup/*";
973 if (!exclude_list_restore.contains(timeshift_path)){
974 exclude_list_restore.add(timeshift_path);
975 }
976
977 log_debug("Main: create_exclude_list_for_restore(): exit");
978
980 }
bool mirror_system
Definition Main.vala:85
bool file_exists(string file_path)
string? file_read(string file_path)

References exclude_list_apps, exclude_list_default, exclude_list_default_extra, exclude_list_home, exclude_list_restore, exclude_list_user, TeeJee.FileSystem.file_exists(), TeeJee.FileSystem.file_read(), TeeJee.Logging.log_debug(), mirror_system, Snapshot.path, TeeJee.FileSystem.path_combine(), and snapshot_to_restore.

Referenced by ExcludeListSummaryWindow.refresh(), and save_exclude_list_for_restore().

◆ create_pre_restore_snapshot_btrfs()

bool Main.create_pre_restore_snapshot_btrfs ( )
inline

Definition at line 3197 of file Main.vala.

3197 {
3198
3199 log_debug("Main: create_pre_restore_snapshot_btrfs()");
3200
3201 string cmd, std_out, std_err;
3202 DateTime dt_created = new DateTime.now_local();
3203 string time_stamp = dt_created.format("%Y-%m-%d_%H-%M-%S");
3204 string snapshot_name = time_stamp;
3205 string snapshot_path = "";
3206
3207 /* Note:
3208 * The @ and @home subvolumes need to be backed-up only if they are in use by the system.
3209 * If user restores a snapshot and then tries to restore another snapshot before the next reboot
3210 * then the @ and @home subvolumes are the ones that were previously restored and need to be deleted.
3211 * */
3212
3213 bool create_pre_restore_backup = false;
3214
3216
3217 // check for an existing pre-restore backup
3218
3219 Snapshot snap_prev = null;
3220 bool found = false;
3221 foreach(var bak in repo.snapshots){
3222 if (bak.live){
3223 found = true;
3224 snap_prev = bak;
3225 log_msg(_("Found existing pre-restore snapshot") + ": %s".printf(bak.name));
3226 break;
3227 }
3228 }
3229
3230 if (found){
3231 //delete system subvolumes
3232 if (sys_subvolumes.has_key("@") && snapshot_to_restore.subvolumes.has_key("@")){
3233 sys_subvolumes["@"].remove();
3234 log_msg(_("Deleted subvolume") + ": @");
3235 }
3236 if (include_btrfs_home_for_restore && sys_subvolumes.has_key("@home") && snapshot_to_restore.subvolumes.has_key("@home")){
3237 sys_subvolumes["@home"].remove();
3238 log_msg(_("Deleted subvolume") + ": @home");
3239 }
3240
3241 //update description for pre-restore backup
3242 snap_prev.description = "Before restoring '%s'".printf(snapshot_to_restore.date_formatted);
3243 snap_prev.update_control_file();
3244 }
3245 else{
3246 create_pre_restore_backup = true;
3247 }
3248 }
3249 else{
3250 create_pre_restore_backup = true;
3251 }
3252
3253 if (create_pre_restore_backup){
3254
3255 log_msg(_("Creating pre-restore snapshot from system subvolumes..."));
3256
3257 dir_create(snapshot_path);
3258
3259 // move subvolumes ----------------
3260
3261 bool no_subvolumes_found = true;
3262
3263 var subvol_list = new Gee.ArrayList<Subvolume>();
3264
3265 var subvol_names = new string[] { "@" };
3267 subvol_names = new string[] { "@","@home" };
3268 }
3269
3270 foreach(string subvol_name in subvol_names){
3271
3272 snapshot_path = path_combine(repo.mount_paths[subvol_name], "bastionguard-backup-btrfs/snapshots/%s".printf(snapshot_name));
3273 dir_create(snapshot_path, true);
3274
3275 string src_path = path_combine(repo.mount_paths[subvol_name], subvol_name);
3276 if (!dir_exists(src_path)){
3277 log_error(_("Could not find system subvolume") + ": %s".printf(subvol_name));
3278 dir_delete(snapshot_path);
3279 continue;
3280 }
3281
3282 no_subvolumes_found = false;
3283
3284 string dst_path = path_combine(snapshot_path, subvol_name);
3285 cmd = "mv '%s' '%s'".printf(src_path, dst_path);
3286 log_debug(cmd);
3287
3288 int status = exec_sync(cmd, out std_out, out std_err);
3289
3290 if (status != 0){
3291 log_error (std_err);
3292 log_error(_("Failed to move system subvolume to snapshot directory") + ": %s".printf(subvol_name));
3293 return false;
3294 }
3295 else{
3296 var subvol_dev = (subvol_name == "@") ? repo.device : repo.device_home;
3297 subvol_list.add(new Subvolume(subvol_name, dst_path, subvol_dev.uuid, repo));
3298
3299 log_msg(_("Moved system subvolume to snapshot directory") + ": %s".printf(subvol_name));
3300 }
3301 }
3302
3303 if (no_subvolumes_found){
3304 //could not find system subvolumes for backing up(!)
3305 log_error(_("Could not find system subvolumes for creating pre-restore snapshot"));
3306 }
3307 else{
3308 // write control file -----------
3309
3310 snapshot_path = path_combine(repo.mount_paths["@"], "bastionguard-backup-btrfs/snapshots/%s".printf(snapshot_name));
3311
3312 var snap = Snapshot.write_control_file(
3313 snapshot_path, dt_created, repo.device.uuid,
3314 LinuxDistro.get_dist_info(path_combine(snapshot_path,"@")).full_name(),
3315 "ondemand", "", 0, true, false, repo);
3316
3317 snap.description = "Before restoring '%s'".printf(snapshot_to_restore.date_formatted);
3318 snap.live = true;
3319
3320 // write subvolume info
3321 foreach(var subvol in subvol_list){
3322 snap.subvolumes.set(subvol.name, subvol);
3323 }
3324
3325 snap.update_control_file(); // save subvolume info
3326
3327 log_msg(_("Created pre-restore snapshot") + ": %s".printf(snap.name));
3328
3330 }
3331 }
3332
3333 return true;
3334 }
bool include_btrfs_home_for_restore
Definition Main.vala:54
Gee.ArrayList< Snapshot?> snapshots
Gee.HashMap< string, string > mount_paths
bool load_snapshots()
Gee.HashMap< string, Subvolume > subvolumes
Definition Snapshot.vala:46
void update_control_file()
string date_formatted
Definition Snapshot.vala:95
Subvolume(string name, string path, string parent_dev_uuid, SnapshotRepo? parent_repo)

References _, Snapshot.date_formatted, SnapshotRepo.device, SnapshotRepo.device_home, TeeJee.FileSystem.dir_create(), TeeJee.FileSystem.dir_exists(), TeeJee.ProcessHelper.exec_sync(), LinuxDistro.get_dist_info(), include_btrfs_home_for_restore, SnapshotRepo.load_snapshots(), TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), TeeJee.Logging.log_msg(), SnapshotRepo.mount_paths, TeeJee.FileSystem.path_combine(), repo, restore_current_system, snapshot_to_restore, SnapshotRepo.snapshots, Subvolume.Subvolume(), Snapshot.subvolumes, sys_subvolumes, Snapshot.update_control_file(), Device.uuid, and Snapshot.write_control_file().

Referenced by restore_execute_btrfs().

◆ create_restore_scripts()

void Main.create_restore_scripts ( out string sh_sync,
out string sh_finish )
inlineprivate

Definition at line 2537 of file Main.vala.

2537 {
2538
2539 log_debug("Main: create_restore_scripts()");
2540
2541 string sh = "export LC_ALL=C.UTF-8\n";
2542
2543 // create scripts --------------------------------------
2544
2545 sh = "";
2546 sh += "echo ''\n";
2548 log_debug("restoring current system");
2549
2550 sh += "echo '" + _("Please do not interrupt the restore process!") + "'\n";
2551 sh += "echo '" + _("System will reboot after files are restored") + "'\n";
2552 }
2553 sh += "echo ''\n";
2554 sh += "sleep 3s\n";
2555
2556 // run rsync ---------------------------------------
2557
2558 sh += "rsync -avir --force --delete --delete-before";
2559
2560 if (dry_run){
2561 sh += " --dry-run";
2562 }
2563
2564 sh += " --log-file=\"%s\"".printf(restore_log_file);
2565 sh += " --exclude-from=\"%s\"".printf(restore_exclude_file);
2566
2567 if (mirror_system){
2568 sh += " \"%s\" \"%s\" \n".printf("/", restore_target_path);
2569 }
2570 else{
2571 sh += " \"%s\" \"%s\" \n".printf(restore_source_path + "/localhost/", restore_target_path);
2572 }
2573
2574 if (dry_run){
2575 sh_sync = sh;
2576 sh_finish = "";
2577 return; // no need to continue
2578 }
2579
2580 sh += "sync \n"; // sync file system
2581
2582 log_debug("rsync script:");
2583 log_debug(sh);
2584
2585 sh_sync = sh;
2586
2587 // chroot and re-install grub2 ---------------------
2588
2589 log_debug("reinstall_grub2=%s".printf(reinstall_grub2.to_string()));
2590 log_debug("grub_device=%s".printf((grub_device == null) ? "null" : grub_device));
2591
2592 var target_distro = LinuxDistro.get_dist_info(restore_target_path);
2593
2594 sh = "";
2595
2596 string chroot = "";
2598 //if ((current_distro.dist_type == "arch") && cmd_exists("arch-chroot")){
2599 //chroot += "arch-chroot \"%s\"".printf(restore_target_path);
2600 //}
2601 //else{
2602 chroot += "chroot \"%s\"".printf(restore_target_path);
2603 //}
2604
2605 // bind system directories for chrooted system
2606 sh += "for i in dev dev/pts proc run sys; do mount --bind \"/$i\" \"%s$i\"; done \n".printf(restore_target_path);
2607 }
2608
2609 if (reinstall_grub2 && (grub_device != null) && (grub_device.length > 0)){
2610
2611 sh += "sync \n";
2612 sh += "echo '' \n";
2613 sh += "echo '" + _("Re-installing GRUB2 bootloader...") + "' \n";
2614
2615 // search for other operating systems
2616 //sh += "chroot \"%s\" os-prober \n".printf(restore_target_path);
2617
2618 // re-install grub ---------------
2619
2620 if (target_distro.dist_type == "redhat"){
2621
2622 // this will run only in clone mode
2623 //sh += "%s grub2-install %s \n".printf(chroot, grub_device);
2624 sh += "%s grub2-install --recheck --force %s \n".printf(chroot, grub_device);
2625
2626 /* NOTE:
2627 * grub2-install should NOT be run on Fedora EFI systems
2628 * https://fedoraproject.org/wiki/GRUB_2
2629 * Instead following packages should be reinstalled:
2630 * dnf reinstall grub2-efi grub2-efi-modules shim
2631 *
2632 * Bootloader installation will be skipped while restoring in GUI mode.
2633 * Fedora seems to boot correctly even after installing new
2634 * kernels and restoring a snapshot with an older kernel.
2635 */
2636 }
2637 else {
2638 //sh += "%s grub-install %s \n".printf(chroot, grub_device);
2639 sh += "%s grub-install --recheck --force %s \n".printf(chroot, grub_device);
2640 }
2641
2642 // create new grub menu
2643 //sh += "chroot \"%s\" grub-mkconfig -o /boot/grub/grub.cfg \n".printf(restore_target_path);
2644 }
2645 else{
2646 log_debug("skipping sh_grub: reinstall_grub2=%s, grub_device=%s".printf(
2647 reinstall_grub2.to_string(), (grub_device == null) ? "null" : grub_device));
2648 }
2649
2650 // update initramfs --------------
2651
2652 if (update_initramfs){
2653 sh += "echo '' \n";
2654 sh += "echo '" + _("Generating initramfs...") + "' \n";
2655
2656 if (target_distro.dist_type == "redhat"){
2657 sh += "%s dracut -f -v \n".printf(chroot);
2658 }
2659 else if (target_distro.dist_type == "arch"){
2660 sh += "%s mkinitcpio -p /etc/mkinitcpio.d/*.preset\n".printf(chroot);
2661 }
2662 else{
2663 sh += "%s update-initramfs -u -k all \n".printf(chroot);
2664 }
2665 }
2666
2667 // update grub menu --------------
2668
2669 if (update_grub){
2670 sh += "echo '' \n";
2671 sh += "echo '" + _("Updating GRUB menu...") + "' \n";
2672
2673 if (target_distro.dist_type == "redhat"){
2674 sh += "%s grub2-mkconfig -o /boot/grub2/grub.cfg \n".printf(chroot);
2675 }
2676 if (target_distro.dist_type == "arch"){
2677 sh += "%s grub-mkconfig -o /boot/grub/grub.cfg \n".printf(chroot);
2678 }
2679 else{
2680 sh += "%s update-grub \n".printf(chroot);
2681 }
2682
2683 sh += "sync \n";
2684 sh += "echo '' \n";
2685 }
2686
2687 // sync file systems
2688 sh += "echo '" + _("Syncing file systems...") + "' \n";
2689 sh += "sync ; sleep 10s; \n";
2690 sh += "echo '' \n";
2691
2693 // unmount chrooted system
2694 sh += "echo '" + _("Cleaning up...") + "' \n";
2695 sh += "for i in dev/pts dev proc run sys; do umount -f \"%s$i\"; done \n".printf(restore_target_path);
2696 sh += "sync \n";
2697 }
2698
2699 log_debug("GRUB2 install script:");
2700 log_debug(sh);
2701
2702 // Perform any post-restore actions
2703 log_debug("Running post-restore tasks...");
2704
2705 sh += "if [ -d \"/etc/bastionguard-backup/restore-hooks.d\" ]; then \n";
2706 sh += " run-parts --verbose /etc/bastionguard-backup/restore-hooks.d \n";
2707 sh += "fi \n";
2708
2709 // reboot if required -----------------------------------
2710
2712 sh += "echo '' \n";
2713 sh += "echo '" + _("Rebooting system...") + "' \n";
2714 sh += "sleep 5s \n";
2715 sh += "reboot -f \n";
2716 //sh_reboot += "shutdown -r now \n";
2717 }
2718
2719 sh_finish = sh;
2720 }
bool update_initramfs
Definition Main.vala:139
bool update_grub
Definition Main.vala:140
string restore_exclude_file
Definition Main.vala:2067
string restore_source_path
Definition Main.vala:2037
string restore_target_path
Definition Main.vala:2050
bool dry_run
Definition Main.vala:100
bool reinstall_grub2
Definition Main.vala:138
string restore_log_file
Definition Main.vala:2061
string grub_device
Definition Main.vala:141

References _, dry_run, LinuxDistro.get_dist_info(), grub_device, TeeJee.Logging.log_debug(), mirror_system, reinstall_grub2, restore_current_system, restore_exclude_file, restore_log_file, restore_source_path, restore_target_path, update_grub, and update_initramfs.

Referenced by restore_execute_rsync().

◆ create_snapshot()

bool Main.create_snapshot ( bool is_ondemand,
Gtk.Window? parent_win )
inline

Definition at line 1082 of file Main.vala.

1082 {
1083
1084 log_debug("Main: create_snapshot()");
1085
1086 bool status = true;
1087 bool update_symlinks = false;
1088
1089 string sys_uuid = (sys_root == null) ? "" : sys_root.uuid;
1090
1091 try
1092 {
1093 if (btrfs_mode && (check_btrfs_layout_system() == false)){
1094 return false;
1095 }
1096
1097 // create a timestamp
1098 DateTime now = new DateTime.now_local();
1099
1100 // check space
1101 if (!repo.has_space()){
1102
1105
1106 // remove invalid snapshots
1107 if (app_mode.length != 0){
1108 repo.auto_remove();
1109 }
1110
1111 // check again ------------
1112
1113 if (!repo.has_space()){
1116 return false;
1117 }
1118 }
1119
1120 // create snapshot root if missing
1121 var f = File.new_for_path(repo.snapshots_path);
1122 if (!f.query_exists()){
1123 log_debug("mkdir: %s".printf(repo.snapshots_path));
1124 f.make_directory_with_parents();
1125 }
1126
1127 // ondemand
1128 if (is_ondemand){
1129 bool ok = create_snapshot_for_tag ("ondemand",now);
1130 if(!ok){
1131 return false;
1132 }
1133 else{
1134 update_symlinks = true;
1135 }
1136 }
1137 else if (scheduled){
1138 Snapshot last_snapshot_boot = repo.get_latest_snapshot("boot", sys_uuid);
1139 Snapshot last_snapshot_hourly = repo.get_latest_snapshot("hourly", sys_uuid);
1140 Snapshot last_snapshot_daily = repo.get_latest_snapshot("daily", sys_uuid);
1141 Snapshot last_snapshot_weekly = repo.get_latest_snapshot("weekly", sys_uuid);
1142 Snapshot last_snapshot_monthly = repo.get_latest_snapshot("monthly", sys_uuid);
1143
1144 DateTime dt_sys_boot = now.add_seconds((-1) * get_system_uptime_seconds());
1145 bool take_new = false;
1146
1147 if (schedule_boot){
1148
1149 log_msg(_("Boot snapshots are enabled"));
1150
1151 if (last_snapshot_boot == null){
1152 log_msg(_("Last boot snapshot not found"));
1153 take_new = true;
1154 }
1155 else if (last_snapshot_boot.date.compare(dt_sys_boot) < 0){
1156 log_msg(_("Last boot snapshot is older than system start time"));
1157 take_new = true;
1158 }
1159 else{
1160 int hours = (int) ((float) now.difference(last_snapshot_boot.date) / TimeSpan.HOUR);
1161 log_msg(_("Last boot snapshot is %d hours old").printf(hours));
1162 take_new = false;
1163 }
1164
1165 if (take_new){
1166 status = create_snapshot_for_tag ("boot",now);
1167 if(!status){
1168 log_error(_("Boot snapshot failed!"));
1169 return false;
1170 }
1171 else{
1172 update_symlinks = true;
1174 }
1175 }
1176 }
1177
1178 if (schedule_hourly){
1179
1180 log_msg(_("Hourly snapshots are enabled"));
1181
1182 if (last_snapshot_hourly == null){
1183 log_msg(_("Last hourly snapshot not found"));
1184 take_new = true;
1185 }
1186 else if (last_snapshot_hourly.date.compare(now.add_hours(-1).add_minutes(1)) < 0){
1187 log_msg(_("Last hourly snapshot is more than 1 hour old"));
1188 take_new = true;
1189 }
1190 else{
1191 int mins = (int) ((float) now.difference(last_snapshot_hourly.date) / TimeSpan.MINUTE);
1192 log_msg(_("Last hourly snapshot is %d minutes old").printf(mins));
1193 take_new = false;
1194 }
1195
1196 if (take_new){
1197 status = create_snapshot_for_tag ("hourly",now);
1198 if(!status){
1199 log_error(_("Hourly snapshot failed!"));
1200 return false;
1201 }
1202 else{
1203 update_symlinks = true;
1205 }
1206 }
1207 }
1208
1209 if (schedule_daily){
1210
1211 log_msg(_("Daily snapshots are enabled"));
1212
1213 if (last_snapshot_daily == null){
1214 log_msg(_("Last daily snapshot not found"));
1215 take_new = true;
1216 }
1217 else if (last_snapshot_daily.date.compare(now.add_days(-1).add_minutes(1)) < 0){
1218 log_msg(_("Last daily snapshot is more than 1 day old"));
1219 take_new = true;
1220 }
1221 else{
1222 int hours = (int) ((float) now.difference(last_snapshot_daily.date) / TimeSpan.HOUR);
1223 log_msg(_("Last daily snapshot is %d hours old").printf(hours));
1224 take_new = false;
1225 }
1226
1227 if (take_new){
1228 status = create_snapshot_for_tag ("daily",now);
1229 if(!status){
1230 log_error(_("Daily snapshot failed!"));
1231 return false;
1232 }
1233 else{
1234 update_symlinks = true;
1236 }
1237 }
1238 }
1239
1240 if (schedule_weekly){
1241
1242 log_msg(_("Weekly snapshots are enabled"));
1243
1244 if (last_snapshot_weekly == null){
1245 log_msg(_("Last weekly snapshot not found"));
1246 take_new = true;
1247 }
1248 else if (last_snapshot_weekly.date.compare(now.add_weeks(-1).add_minutes(1)) < 0){
1249 log_msg(_("Last weekly snapshot is more than 1 week old"));
1250 take_new = true;
1251 }
1252 else{
1253 int days = (int) ((float) now.difference(last_snapshot_weekly.date) / TimeSpan.DAY);
1254 log_msg(_("Last weekly snapshot is %d days old").printf(days));
1255 take_new = false;
1256 }
1257
1258 if (take_new){
1259 status = create_snapshot_for_tag ("weekly",now);
1260 if(!status){
1261 log_error(_("Weekly snapshot failed!"));
1262 return false;
1263 }
1264 else{
1265 update_symlinks = true;
1267 }
1268 }
1269 }
1270
1271 if (schedule_monthly){
1272
1273 log_msg(_("Monthly snapshot are enabled"));
1274
1275 if (last_snapshot_monthly == null){
1276 log_msg(_("Last monthly snapshot not found"));
1277 take_new = true;
1278 }
1279 else if (last_snapshot_monthly.date.compare(now.add_months(-1).add_minutes(1)) < 0){
1280 log_msg(_("Last monthly snapshot is more than 1 month old"));
1281 take_new = true;
1282 }
1283 else{
1284 int days = (int) ((float) now.difference(last_snapshot_monthly.date) / TimeSpan.DAY);
1285 log_msg(_("Last monthly snapshot is %d days old").printf(days));
1286 take_new = false;
1287 }
1288
1289 if (take_new){
1290 status = create_snapshot_for_tag ("monthly",now);
1291 if(!status){
1292 log_error(_("Monthly snapshot failed!"));
1293 return false;
1294 }
1295 else{
1296 update_symlinks = true;
1298 }
1299 }
1300 }
1301 }
1302 else{
1303 log_msg(_("Scheduled snapshots are disabled") + " - " + _("Nothing to do!"));
1305 }
1306
1307 log_msg(string.nfill(78, '-'));
1308
1309 repo.load_snapshots(); // reload list for new snapshot
1310
1311 if (app_mode.length != 0){
1312 repo.auto_remove();
1314 }
1315
1316 if (update_symlinks){
1318 }
1319
1320 //log_msg("OK");
1321 }
1322 catch(Error e){
1323 log_error (e.message);
1324 return false;
1325 }
1326
1327 return status;
1328 }
Device sys_root
Definition Main.vala:75
bool schedule_hourly
Definition Main.vala:90
bool schedule_boot
Definition Main.vala:91
bool schedule_monthly
Definition Main.vala:87
bool create_snapshot_for_tag(string tag, DateTime dt_created)
Definition Main.vala:1330
bool scheduled
Definition Main.vala:1050
bool schedule_weekly
Definition Main.vala:88
bool check_btrfs_layout_system(Gtk.Window? win=null)
Definition Main.vala:480
void cron_job_update()
Definition Main.vala:4463
bool schedule_daily
Definition Main.vala:89
Snapshot? get_latest_snapshot(string tag, string sys_uuid)
bool has_space(uint64 needed=0)
string snapshots_path
void create_symlinks()
DateTime date
Definition Snapshot.vala:38
double get_system_uptime_seconds()

References _, app_mode, SnapshotRepo.auto_remove(), btrfs_mode, check_btrfs_layout_system(), create_snapshot_for_tag(), SnapshotRepo.create_symlinks(), cron_job_update(), Snapshot.date, Error, SnapshotRepo.get_latest_snapshot(), TeeJee.System.get_system_uptime_seconds(), SnapshotRepo.has_space(), SnapshotRepo.load_snapshots(), TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), TeeJee.Logging.log_msg(), repo, schedule_boot, schedule_daily, schedule_hourly, schedule_monthly, schedule_weekly, scheduled, SnapshotRepo.snapshots_path, SnapshotRepo.status_details, SnapshotRepo.status_message, sys_root, and Device.uuid.

Referenced by AppConsole.create_snapshot(), and BackupBox.take_snapshot_thread().

◆ create_snapshot_for_tag()

bool Main.create_snapshot_for_tag ( string tag,
DateTime dt_created )
inlineprivate

Definition at line 1330 of file Main.vala.

1330 {
1331
1332 log_debug("Main: backup_and_rotate()");
1333
1334 // save start time
1335 var dt_begin = new DateTime.now_local();
1336 bool status = true;
1337
1338 // get system boot time
1339 DateTime now = new DateTime.now_local();
1340 DateTime dt_sys_boot = now.add_seconds((-1) * get_system_uptime_seconds());
1341
1342 // check if we can rotate an existing backup -------------
1343
1344 DateTime dt_filter = null;
1345
1346 if (tag != "ondemand"){
1347 switch(tag){
1348 case "boot":
1349 dt_filter = dt_sys_boot;
1350 break;
1351 case "hourly":
1352 case "daily":
1353 case "weekly":
1354 case "monthly":
1355 dt_filter = now.add_hours(-1).add_seconds(59);
1356 break;
1357 default:
1358 log_error(_("Unknown snapshot type") + ": %s".printf(tag));
1359 return false;
1360 }
1361
1362 // find a recent backup that can be used
1363 Snapshot backup_to_rotate = null;
1364 foreach(var bak in repo.snapshots){
1365 if (bak.date.compare(dt_filter) > 0){
1366 backup_to_rotate = bak;
1367 break;
1368 }
1369 }
1370
1371 if (backup_to_rotate != null){
1372
1373 // tag the backup
1374 backup_to_rotate.add_tag(tag);
1375
1376 var message = _("Tagged snapshot") + " '%s': %s".printf(backup_to_rotate.name, tag);
1377 log_msg(message);
1378
1379 return true;
1380 }
1381 }
1382
1383 if (!repo.available()) {
1386 exit_app();
1387 }
1388
1389
1390 if (repo.mount_path.length == 0){
1391 log_error("Backup location not mounted");
1392 exit_app();
1393 }
1394
1395 // create new snapshot -----------------------
1396 Snapshot new_snapshot = null;
1397 if (btrfs_mode)
1398 {
1399 new_snapshot = create_snapshot_with_btrfs(tag, dt_created);
1400 }
1401 else
1403 {
1404 // Perform a dry-run of the intended backup and make sure we'll have enough room
1405 uint64 needed = get_space_needed_for_rsync_snapshot(dt_created);
1406 bool enough = repo.has_space(needed);
1407
1408 var message = "Space required for snapshot: %lld (%s). Space available: %lu (%s)"
1409 .printf(needed, format_file_size(needed), repo.device.free_bytes, repo.device.free);
1410 log_msg(message);
1411 if (!enough)
1412 {
1413 message = "Not enough disk space! Additional required: %lld (%s)".printf(needed - repo.device.free_bytes, format_file_size(needed - repo.device.free_bytes));
1414 log_msg(message);
1415 }
1416
1417 if (enough)
1418 {
1419 new_snapshot = create_snapshot_with_rsync(tag, dt_created);
1420 }
1421 else
1422 {
1423 return false;
1424 }
1425 }
1426 else
1427 {
1428 // this is the initial snapshot (which means a size check has already been made) or the target
1429 // drive's available space is more than the the original (full) snapshot's size.
1430 new_snapshot = create_snapshot_with_rsync(tag, dt_created);
1431 }
1432 // finish ------------------------------
1433
1434 var dt_end = new DateTime.now_local();
1435 TimeSpan elapsed = dt_end.difference(dt_begin);
1436 long seconds = (long)(elapsed * 1.0 / TimeSpan.SECOND);
1437
1438 var message = "";
1439 if (new_snapshot != null){
1440 message = "%s %s (%lds)".printf((btrfs_mode ? "BTRFS" : "RSYNC"), _("Snapshot saved successfully"), seconds);
1441 }
1442 else{
1443 message = _("Failed to create snapshot");
1444 }
1445
1446 log_msg(message);
1447 OSDNotify.notify_send("TimeShift", message, 10000, "low");
1448
1449 if (new_snapshot != null){
1450 message = _("Tagged snapshot") + " '%s': %s".printf(new_snapshot.name, tag);
1451 log_msg(message);
1452 }
1453
1454 return status;
1455 }
string free
Definition Device.vala:146
uint64 free_bytes
Definition Device.vala:120
Snapshot? create_snapshot_with_rsync(string tag, DateTime dt_created)
Definition Main.vala:1557
static uint64 first_snapshot_size
Definition Main.vala:123
Snapshot? create_snapshot_with_btrfs(string tag, DateTime dt_created)
Definition Main.vala:1718
uint64 get_space_needed_for_rsync_snapshot(DateTime dt_created)
Definition Main.vala:1457
string name
Definition Snapshot.vala:37
void add_tag(string tag)
string format_file_size(uint64 size, bool binary_units=false, string unit="", bool show_units=true, int decimals=1)

References _, SnapshotRepo.available(), btrfs_mode, create_snapshot_with_btrfs(), create_snapshot_with_rsync(), SnapshotRepo.device, exit_app(), first_snapshot_size, TeeJee.FileSystem.format_file_size(), Device.free, Device.free_bytes, get_space_needed_for_rsync_snapshot(), TeeJee.System.get_system_uptime_seconds(), SnapshotRepo.has_space(), TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), TeeJee.Logging.log_msg(), SnapshotRepo.mount_path, Snapshot.name, OSDNotify.notify_send(), repo, SnapshotRepo.snapshots, SnapshotRepo.status_details, and SnapshotRepo.status_message.

Referenced by create_snapshot().

◆ create_snapshot_with_btrfs()

Snapshot? Main.create_snapshot_with_btrfs ( string tag,
DateTime dt_created )
inlineprivate

Definition at line 1718 of file Main.vala.

1718 {
1719
1720 log_msg(_("Creating new backup...") + "(BTRFS)");
1721
1722 log_msg(_("Saving to device") + ": %s".printf(repo.device.device) + ", " + _("mounted at path") + ": %s".printf(repo.mount_paths["@"]));
1723 if ((repo.device_home != null) && (repo.device_home.uuid != repo.device.uuid)){
1724 log_msg(_("Saving to device") + ": %s".printf(repo.device_home.device) + ", " + _("mounted at path") + ": %s".printf(repo.mount_paths["@home"]));
1725 }
1726
1727 // take new backup ---------------------------------
1728
1729 if (repo.mount_path.length == 0){
1730 log_error("Snapshot device not mounted");
1731 exit_app();
1732 }
1733
1734 string time_stamp = dt_created.format("%Y-%m-%d_%H-%M-%S");
1735 string snapshot_name = time_stamp;
1736 string sys_uuid = (sys_root == null) ? "" : sys_root.uuid;
1737 string snapshot_path = "";
1738
1739 // create subvolume snapshots
1740
1741 var subvol_names = new string[] { "@" };
1742
1744
1745 subvol_names = new string[] { "@","@home" };
1746 }
1747
1748 foreach(var subvol_name in subvol_names){
1749
1750 snapshot_path = path_combine(repo.mount_paths[subvol_name], "bastionguard-backup-btrfs/snapshots/%s".printf(snapshot_name));
1751
1752 dir_create(snapshot_path, true);
1753
1754 string src_path = path_combine(repo.mount_paths[subvol_name], subvol_name);
1755
1756 string dst_path = path_combine(snapshot_path, subvol_name);
1757
1758 // Dirty hack to fix the nested subvilumes issue (cause of issue is unknown)
1759 if (dst_path.has_suffix("/@/@")){
1760 dst_path = dst_path.replace("/@/@", "/@");
1761 }
1762 else if (dst_path.has_suffix("/@home/@home")){
1763 dst_path = dst_path.replace("/@home/@home", "/@home");
1764 }
1765
1766 string cmd = "btrfs subvolume snapshot '%s' '%s' \n".printf(src_path, dst_path);
1767
1768 if (LOG_COMMANDS) { log_debug(cmd); }
1769
1770 string std_out, std_err;
1771
1772 int ret_val = exec_sync(cmd, out std_out, out std_err);
1773
1774 if (ret_val != 0){
1775
1776 log_error (std_err);
1777 log_error(_("btrfs returned an error") + ": %d".printf(ret_val));
1778 log_error(_("Failed to create subvolume snapshot") + ": %s".printf(subvol_name));
1779 return null;
1780 }
1781 else{
1782 log_msg(_("Created subvolume snapshot") + ": %s".printf(dst_path));
1783 }
1784 }
1785
1786 //log_msg(_("Writing control file..."));
1787
1788 snapshot_path = path_combine(repo.mount_paths["@"], "bastionguard-backup-btrfs/snapshots/%s".printf(snapshot_name));
1789
1790 string initial_tags = (tag == "ondemand") ? "" : tag;
1791
1792 // write control file
1793 var snapshot = Snapshot.write_control_file(
1794 snapshot_path, dt_created, sys_uuid, current_distro.full_name(),
1795 initial_tags, cmd_comments, 0, true, false, repo);
1796
1797 // write subvolume info
1798 foreach(var subvol in sys_subvolumes.values){
1799 snapshot.subvolumes.set(subvol.name, subvol);
1800 }
1801 snapshot.update_control_file(); // save subvolume info
1802
1803 set_tags(snapshot); // set_tags() will update the control file
1804
1805 // Perform any post-backup actions
1806 this.run_post_backup_hooks(snapshot_path);
1807
1808 return snapshot;
1809 }
string device
Definition Device.vala:44
void run_post_backup_hooks(string snapshot_path)
Definition Main.vala:1811
string cmd_comments
Definition Main.vala:152
void set_tags(Snapshot snapshot)
Definition Main.vala:1827

References _, cmd_comments, current_distro, Device.device, SnapshotRepo.device, SnapshotRepo.device_home, TeeJee.FileSystem.dir_create(), TeeJee.ProcessHelper.exec_sync(), exit_app(), LinuxDistro.full_name(), include_btrfs_home_for_backup, TeeJee.Logging.LOG_COMMANDS, TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), TeeJee.Logging.log_msg(), SnapshotRepo.mount_path, SnapshotRepo.mount_paths, TeeJee.FileSystem.path_combine(), repo, run_post_backup_hooks(), set_tags(), sys_root, sys_subvolumes, Snapshot.update_control_file(), Device.uuid, and Snapshot.write_control_file().

Referenced by create_snapshot_for_tag().

◆ create_snapshot_with_rsync()

Snapshot? Main.create_snapshot_with_rsync ( string tag,
DateTime dt_created )
inlineprivate

Definition at line 1557 of file Main.vala.

1557 {
1558 log_msg(string.nfill(78, '-'));
1559
1560 if (first_snapshot_size == 0){
1561 log_msg(_("Estimating system size..."));
1563 }
1564
1565 log_msg(_("Creating new snapshot...") + "(RSYNC)");
1566
1567 log_msg(_("Saving to device") + ": %s".printf(repo.device.device) + ", " + _("mounted at path") + ": %s".printf(repo.mount_path));
1568
1569 // take new backup ---------------------------------
1570
1571 if (repo.mount_path.length == 0){
1572 log_error("Backup location not mounted");
1573 exit_app();
1574 }
1575
1576 string time_stamp = dt_created.format("%Y-%m-%d_%H-%M-%S");
1577 string snapshot_dir = repo.snapshots_path;
1578 string snapshot_name = time_stamp;
1579 string snapshot_path = path_combine(snapshot_dir, snapshot_name);
1580 dir_create(snapshot_path);
1581 string localhost_path = path_combine(snapshot_path, "localhost");
1582 dir_create(localhost_path);
1583
1584 string sys_uuid = (sys_root == null) ? "" : sys_root.uuid;
1585
1586 Snapshot snapshot_to_link = null;
1587
1588 // check if a snapshot was restored recently and use it for linking ---------
1589
1590 try{
1591
1592 string ctl_path = path_combine(snapshot_dir, ".sync-restore");
1593 var f = File.new_for_path(ctl_path);
1594
1595 if (f.query_exists()){
1596
1597 // read snapshot name from file
1598 string snap_path = file_read(ctl_path);
1599 string snap_name = file_basename(snap_path);
1600
1601 // find the snapshot that was restored
1602 foreach(var bak in repo.snapshots){
1603 if ((bak.name == snap_name) && (bak.sys_uuid == sys_uuid)){
1604 // use for linking
1605 snapshot_to_link = bak;
1606 // delete the restore-control-file
1607 f.delete();
1608 break;
1609 }
1610 }
1611 }
1612 }
1613 catch(Error e){
1614 log_error (e.message);
1615 return null;
1616 }
1617
1618 // get latest snapshot to link if not set -------
1619
1620 if (snapshot_to_link == null){
1621 snapshot_to_link = repo.get_latest_snapshot("", sys_uuid);
1622 }
1623
1624 string link_from_path = "";
1625 if (snapshot_to_link != null){
1626 log_msg("%s: %s".printf(_("Linking from snapshot"), snapshot_to_link.name));
1627 link_from_path = "%s/localhost/".printf(snapshot_to_link.path);
1628 }
1629
1630 // save exclude list ----------------
1631
1632 string? exclude_from_file = save_exclude_list_for_backup(snapshot_path);
1633
1634 if (null == exclude_from_file){
1635 log_error(_("Failed to save exclude list"));
1636 return null;
1637 }
1638
1639 // rsync file system -------------------
1640
1641 progress_text = _("Syncing files with rsync...");
1643
1644 var log_file = snapshot_path + "/rsync-log";
1646
1647 task = new RsyncTask();
1648
1649 task.source_path = "";
1650 task.dest_path = snapshot_path + "/localhost/";
1651 task.link_from_path = link_from_path;
1652 task.exclude_from_file = exclude_from_file;
1653 task.rsync_log_file = log_file;
1654 task.prg_count_total = Main.first_snapshot_count;
1655
1656 task.relative = true;
1657 task.verbose = true;
1658 task.delete_extra = true;
1659 task.delete_excluded = true;
1660 task.delete_after = false;
1661
1662 if (app_mode.length > 0){
1663 // console mode
1664 task.io_nice = true;
1665 }
1666
1667 task.execute();
1668
1669 while (this.task.status == AppStatus.RUNNING || this.task.status == AppStatus.PAUSED){
1670 sleep(1000);
1671 gtk_do_events();
1672
1673 stdout.printf("%6.2f%% %s (%s %s)\r".printf(task.progress * 100.0, _("complete"), task.stat_time_remaining, _("remaining")));
1674 stdout.flush();
1675 }
1676
1677 stdout.printf(string.nfill(80, ' '));
1678 stdout.flush();
1679
1680 stdout.printf("\r");
1681 stdout.flush();
1682
1683 if (task.total_size == 0){
1684 log_error(_("rsync returned an error"));
1685 log_error(_("Failed to create new snapshot"));
1686 return null;
1687 }
1688
1689 string initial_tags = (tag == "ondemand") ? "" : tag;
1690
1691 // write control file
1692 // this step is redundant - just in case if app crashes while parsing log file in next step
1693 //Snapshot.write_control_file(
1694 // snapshot_path, dt_created, sys_uuid, current_distro.full_name(),
1695 // initial_tags, cmd_comments, 0, false, false, repo);
1696
1697 // parse log file
1698 //progress_text = _("Parsing log file...");
1699 //log_msg(progress_text);
1700 //var task = new RsyncTask();
1701 //task.parse_log(log_file);
1702
1703 int64 fcount = file_line_count(log_file);
1704
1705 // write control file (final - with file count after parsing log)
1706 var snapshot = Snapshot.write_control_file(
1707 snapshot_path, dt_created, sys_uuid, current_distro.full_name(),
1708 initial_tags, cmd_comments, fcount, false, false, repo);
1709
1710 set_tags(snapshot); // set_tags() will update the control file
1711
1712 // Perform any post-backup actions
1713 this.run_post_backup_hooks(snapshot_path);
1714
1715 return snapshot;
1716 }
AppStatus
string??? stat_time_remaining
virtual void execute()
AppStatus status
double progress
string progress_text
Definition Main.vala:156
Main(string[] args, bool gui_mode)
Definition Main.vala:186
uint64 estimate_system_size(progressCallback? callback=null)
Definition Main.vala:4168
string? save_exclude_list_for_backup(string output_path)
Definition Main.vala:984
int64 total_size
string file_basename(string file_path)
bool file_delete(string file_path)
int64? file_line_count(string file_path)
void sleep(int milliseconds)

References _, app_mode, cmd_comments, current_distro, Device.device, SnapshotRepo.device, TeeJee.FileSystem.dir_create(), Error, estimate_system_size(), AsyncTask.execute(), exit_app(), TeeJee.FileSystem.file_basename(), TeeJee.FileSystem.file_delete(), TeeJee.FileSystem.file_line_count(), TeeJee.FileSystem.file_read(), first_snapshot_size, LinuxDistro.full_name(), SnapshotRepo.get_latest_snapshot(), TeeJee.GtkHelper.gtk_do_events(), TeeJee.Logging.log_error(), log_file, TeeJee.Logging.log_msg(), Main(), SnapshotRepo.mount_path, Snapshot.name, Snapshot.path, TeeJee.FileSystem.path_combine(), AsyncTask.progress, progress_text, repo, RsyncTask.RsyncTask(), run_post_backup_hooks(), save_exclude_list_for_backup(), set_tags(), TeeJee.System.sleep(), SnapshotRepo.snapshots, SnapshotRepo.snapshots_path, AsyncTask.stat_time_remaining, AsyncTask.status, sys_root, task, RsyncTask.total_size, Device.uuid, and Snapshot.write_control_file().

Referenced by create_snapshot_for_tag().

◆ cron_job_update()

void Main.cron_job_update ( )
inline

Definition at line 4463 of file Main.vala.

4463 {
4464
4465 if (live_system()) { return; }
4466
4467 // remove entries created by previous versions -----------
4468
4469 string entry = "bastionguard-backup --backup";
4470
4471 int count = 0;
4472 while (CronTab.has_job(entry, true, false)){
4473
4474 CronTab.remove_job(entry, true, true);
4475
4476 if (++count == 100){
4477 break;
4478 }
4479 }
4480
4481 entry = "bastionguard-backup-btrfs --backup";
4482
4483 count = 0;
4484 while (CronTab.has_job(entry, true, false)){
4485
4486 CronTab.remove_job(entry, true, true);
4487
4488 if (++count == 100){
4489 break;
4490 }
4491 }
4492
4493 // Rimuovi vecchi file cron BastionGuardBackup legacy
4494 CronTab.remove_script_file("bastionguard-backup-hourly", "d");
4495 CronTab.remove_script_file("bastionguard-backup-boot", "d");
4496 CronTab.remove_script_file("bastionguard-backup-hourly", "hourly");
4497
4498 CronTab.remove_script_file("bastionguard-backup-hourly", "hourly");
4499
4500 // start update ---------------------------
4501
4502 if (scheduled){
4503
4504 //hourly
4505 CronTab.add_script_file("bastionguard-backup-hourly", "d", "0 * * * * root bastionguard-backup --check --scripted", stop_cron_emails);
4506
4507 //boot
4508 if (schedule_boot){
4509 CronTab.add_script_file("bastionguard-backup-boot", "d", "@reboot root sleep 10m && bastionguard-backup --create --scripted --tags B", stop_cron_emails);
4510 }
4511 else{
4512 CronTab.remove_script_file("bastionguard-backup-boot", "d");
4513 }
4514 }
4515 else{
4516 CronTab.remove_script_file("bastionguard-backup-hourly", "d");
4517 CronTab.remove_script_file("bastionguard-backup-boot", "d");
4518 }
4519 }
bool stop_cron_emails
Definition Main.vala:57
bool live_system()
Definition Main.vala:1058

References CronTab.add_script_file(), CronTab.has_job(), live_system(), CronTab.remove_job(), CronTab.remove_script_file(), schedule_boot, scheduled, and stop_cron_emails.

Referenced by create_snapshot(), exit_app(), BackupWindow.save_changes(), RestoreWindow.save_changes(), SettingsWindow.save_changes(), and SetupWizardWindow.save_changes().

◆ delete_begin()

void Main.delete_begin ( )
inline

Definition at line 1882 of file Main.vala.

1882 {
1883
1884 log_debug("Main: delete_begin()");
1885 progress_text = _("Preparing...");
1886
1887 try {
1888 thread_delete_running = true;
1889 thread_delete_success = false;
1890 new Thread<void>.try ("delete", () => {delete_thread();});
1891
1892 //new Thread<bool> ("", delete_thread);
1893
1894 log_debug("delete_begin(): thread created");
1895 }
1896 catch (Error e) {
1897 thread_delete_running = false;
1898 thread_delete_success = false;
1899 log_error (e.message);
1900 }
1901
1902 log_debug("Main: delete_begin(): exit");
1903 }
bool thread_delete_success
Definition Main.vala:109
void delete_thread()
Definition Main.vala:1905
bool thread_delete_running
Definition Main.vala:108

References _, delete_thread(), Error, TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), progress_text, thread_delete_running, and thread_delete_success.

Referenced by DeleteBox.delete_snapshots().

◆ delete_thread()

void Main.delete_thread ( )
inline

Definition at line 1905 of file Main.vala.

1905 {
1906
1907 log_debug("delete_thread()");
1908
1909 bool status = true;
1910
1911 foreach(var bak in delete_list){
1912 bak.mark_for_deletion();
1913 }
1914
1915 while (delete_list.size > 0){
1916
1917 var bak = delete_list[0];
1918 bak.mark_for_deletion(); // mark for deletion again since initial list may have changed
1919
1920 if (btrfs_mode){
1921 status = bak.remove(true); // wait till complete
1922
1923 var message = "%s '%s'".printf(_("Removed"), bak.name);
1924 OSDNotify.notify_send("TimeShift", message, 10000, "low");
1925 }
1926 else{
1927
1928 delete_file_task = bak.delete_file_task;
1929 delete_file_task.prg_count_total = (int64) Main.first_snapshot_count;
1930
1931 status = bak.remove(true); // wait till complete
1932
1933 if (delete_file_task.status != AppStatus.CANCELLED){
1934 var message = "%s '%s' (%s)".printf(_("Removed"), bak.name, delete_file_task.stat_time_elapsed);
1935 OSDNotify.notify_send("TimeShift", message, 10000, "low");
1936 }
1937 }
1938
1939 delete_list.remove(bak);
1940 }
1941
1942 thread_delete_running = false;
1943 thread_delete_success = status;
1944 }
string stat_time_elapsed

References _, btrfs_mode, delete_file_task, delete_list, TeeJee.Logging.log_debug(), Main(), OSDNotify.notify_send(), AsyncTask.stat_time_elapsed, AsyncTask.status, thread_delete_running, and thread_delete_success.

Referenced by delete_begin().

◆ detect_encrypted_dirs()

void Main.detect_encrypted_dirs ( )
inlineprivate

Definition at line 593 of file Main.vala.

593 {
594
595 current_system_users = SystemUser.read_users_from_file("/etc/passwd");
596
597 string txt = "";
601
602 foreach(var user in current_system_users.values){
603
604 if (user.is_system) { continue; }
605
606 if (txt.length > 0) { txt += " "; }
607 txt += "%s".printf(user.name);
608
609 if (user.has_encrypted_home){
610
611 users_with_encrypted_home += " %s".printf(user.name);
612
613 encrypted_home_dirs += "%s\n".printf(user.home_path);
614 }
615
616 if (user.has_encrypted_private_dirs){
617
618 foreach(string enc_path in user.encrypted_private_dirs){
619 encrypted_private_dirs += "%s\n".printf(enc_path);
620 }
621 }
622 }
624
625 log_debug("Users: %s".printf(txt));
626 log_debug("Encrypted home users: %s".printf(users_with_encrypted_home));
627 log_debug("Encrypted home dirs:\n%s".printf(encrypted_home_dirs));
628 log_debug("Encrypted private dirs:\n%s".printf(encrypted_private_dirs));
629 }
string users_with_encrypted_home
Definition Main.vala:165
string encrypted_home_dirs
Definition Main.vala:166
string encrypted_private_dirs
Definition Main.vala:171

References current_system_users, encrypted_home_dirs, encrypted_private_dirs, TeeJee.Logging.log_debug(), SystemUser.read_users_from_file(), and users_with_encrypted_home.

Referenced by Main().

◆ detect_system_devices()

void Main.detect_system_devices ( )
inline

Definition at line 3842 of file Main.vala.

3842 {
3843
3844 log_debug("detect_system_devices()");
3845
3846 sys_root = null;
3847 sys_boot = null;
3848 sys_efi = null;
3849 sys_home = null;
3850
3851 foreach(var pi in partitions){
3852
3853 foreach(var mp in pi.mount_points){
3854
3855 // skip loop devices - Fedora Live uses loop devices containing ext4-formatted lvm volumes
3856 if ((pi.type == "loop") || (pi.has_parent() && (pi.parent.type == "loop"))){
3857 continue;
3858 }
3859
3860 if (mp.mount_point == "/"){
3861 sys_root = pi;
3862 if ((app_mode == "")||(LOG_DEBUG)){
3863 string txt = _("/ is mapped to device") + ": %s, UUID=%s".printf(pi.device,pi.uuid);
3864 if (mp.subvolume_name().length > 0){
3865 txt += ", subvol=%s".printf(mp.subvolume_name());
3866 }
3867 log_debug(txt);
3868 }
3869 }
3870
3871 if (mp.mount_point == "/home"){
3872 sys_home = pi;
3873 if ((app_mode == "")||(LOG_DEBUG)){
3874 string txt = _("/home is mapped to device") + ": %s, UUID=%s".printf(pi.device,pi.uuid);
3875 if (mp.subvolume_name().length > 0){
3876 txt += ", subvol=%s".printf(mp.subvolume_name());
3877 }
3878 log_debug(txt);
3879 }
3880 }
3881
3882 if (mp.mount_point == "/boot"){
3883 sys_boot = pi;
3884 if ((app_mode == "")||(LOG_DEBUG)){
3885 string txt = _("/boot is mapped to device") + ": %s, UUID=%s".printf(pi.device,pi.uuid);
3886 if (mp.subvolume_name().length > 0){
3887 txt += ", subvol=%s".printf(mp.subvolume_name());
3888 }
3889 log_debug(txt);
3890 }
3891 }
3892
3893 if (mp.mount_point == "/boot/efi"){
3894 sys_efi = pi;
3895 if ((app_mode == "")||(LOG_DEBUG)){
3896 string txt = _("/boot/efi is mapped to device") + ": %s, UUID=%s".printf(pi.device,pi.uuid);
3897 if (mp.subvolume_name().length > 0){
3898 txt += ", subvol=%s".printf(mp.subvolume_name());
3899 }
3900 log_debug(txt);
3901 }
3902 }
3903
3904 }
3905 }
3906
3907 sys_subvolumes = Subvolume.detect_subvolumes_for_system_by_path("/", null, parent_window);
3908 }
Device sys_boot
Definition Main.vala:76
Device sys_home
Definition Main.vala:78
Device sys_efi
Definition Main.vala:77

References _, app_mode, Subvolume.detect_subvolumes_for_system_by_path(), TeeJee.Logging.LOG_DEBUG, TeeJee.Logging.log_debug(), parent_window, partitions, sys_boot, sys_efi, sys_home, sys_root, and sys_subvolumes.

Referenced by Main().

◆ estimate_system_size()

uint64 Main.estimate_system_size ( progressCallback? callback = null)
inline

Definition at line 4168 of file Main.vala.

4168 {
4169
4170 log_debug("estimate_system_size()");
4171
4172 if (Main.first_snapshot_size > 0){
4173 return Main.first_snapshot_size;
4174 }
4175 else if (live_system()){
4176 return 0;
4177 }
4178
4179 // create a RsyncTask in dry_run mode to estimate the amount of work needed to do
4180 string dir_empty = path_combine(TEMP_DIR, "empty");
4181 dir_create(dir_empty);
4182
4183 task = new RsyncTask();
4184
4185 task.dest_path = dir_empty;
4186 task.exclude_from_file = save_exclude_list_for_backup(TEMP_DIR) ?? "";
4187
4188 task.delete_extra = true;
4189 task.delete_excluded = true;
4190 task.delete_after = false;
4191
4192 if (app_mode.length > 0){
4193 // console mode
4194 task.io_nice = true;
4195 }
4196
4197 task.dry_run = true;
4198
4199 task.execute();
4200
4201 while (task.status == AppStatus.RUNNING){
4202 Thread.usleep((ulong) GLib.TimeSpan.MILLISECOND * 16); // ~60fps
4203 if (callback != null) callback();
4204 gtk_do_events();
4205 }
4206
4207 Main.first_snapshot_size = task.total_size;
4208 Main.first_snapshot_count = task.count_created;
4209 if ((task.total_size == 0) && (sys_root != null)) {
4210 Main.first_snapshot_size = sys_root.used_bytes;
4211 }
4212
4214
4215 log_debug("estimate_system_size(): ok");
4216
4217 return Main.first_snapshot_size;
4218 }
uint64 used_bytes
Definition Device.vala:78
void save_app_config()
Definition Main.vala:3338
int64 count_created

References app_mode, RsyncTask.count_created, TeeJee.FileSystem.dir_create(), AsyncTask.execute(), first_snapshot_count, first_snapshot_size, TeeJee.GtkHelper.gtk_do_events(), live_system(), TeeJee.Logging.log_debug(), Main(), TeeJee.FileSystem.path_combine(), progressCallback(), RsyncTask.RsyncTask(), save_app_config(), save_exclude_list_for_backup(), AsyncTask.status, sys_root, task, TeeJee.ProcessHelper.TEMP_DIR, RsyncTask.total_size, and Device.used_bytes.

Referenced by create_snapshot_with_rsync(), and EstimateBox.estimate_system_size().

◆ exit_app()

void Main.exit_app ( int exit_code = 0)
inline

Definition at line 4574 of file Main.vala.

4574 {
4575
4576 log_debug("exit_app()");
4577
4578 if (app_mode == ""){
4579 //update app config only in GUI mode
4581 }
4582
4584
4585 unmount_target_device(false);
4586
4587 clean_logs();
4588
4589 app_lock.remove();
4590
4591 dir_delete(TEMP_DIR);
4592
4594
4595 exit(exit_code);
4596
4597 //Gtk.main_quit ();
4598 }
void remove()
Definition AppLock.vala:76
void cleanup_unmount_devices()
Definition Main.vala:4600
void unmount_target_device(bool exit_on_error=true)
Definition Main.vala:4019
void clean_logs()
Definition Main.vala:4523

References app_lock, app_mode, clean_logs(), cleanup_unmount_devices(), cron_job_update(), exit(), TeeJee.Logging.log_debug(), AppLock.remove(), save_app_config(), TeeJee.ProcessHelper.TEMP_DIR, and unmount_target_device().

Referenced by AppConsole.confirm_restore(), create_snapshot_for_tag(), create_snapshot_with_btrfs(), create_snapshot_with_rsync(), initialize_repo(), Main(), AppConsole.main(), AppGtk.main(), AppConsole.map_devices(), MainWindow.on_close_request(), AppConsole.parse_arguments(), AppGtk.parse_arguments(), AppConsole.read_stdin_device(), AppConsole.read_stdin_device_mounts(), AppConsole.read_stdin_grub_install(), AppConsole.read_stdin_restore_confirm(), AppConsole.read_stdin_snapshot(), MainWindow.restart_application(), AppConsole.select_grub_device(), AppConsole.select_snapshot(), AppConsole.select_snapshot_device(), AppConsole.select_snapshot_for_deletion(), AppConsole.select_snapshot_for_restore(), unmount_device(), and validate_cmd_tags().

◆ fix_crypttab_file()

void Main.fix_crypttab_file ( string target_path)
inlineprivate

Definition at line 2988 of file Main.vala.

2988 {
2989
2990 log_debug("Main: fix_crypttab_file()");
2991
2992 string crypttab_path = path_combine(target_path, "etc/crypttab");
2993
2994 if (!file_exists(crypttab_path)){
2995 log_debug("File not found: %s".printf(crypttab_path));
2996 return;
2997 }
2998
2999 var crypttab_list = CryptTabEntry.read_file(crypttab_path);
3000
3001 // add option "nofail" to existing entries
3002
3003 log_debug("checking for 'nofail' option...");
3004
3005 foreach(var entry in crypttab_list){
3006 entry.append_option("nofail");
3007 }
3008
3009 log_debug("updating entries...");
3010
3011 // check and add entries for mapped devices which are encrypted
3012
3013 foreach(var mnt in mount_list){
3014 if ((mnt.device != null) && (mnt.device.parent != null)
3015 && ((mnt.device.is_on_encrypted_partition())
3016 || ((mnt.device.parent.parent != null) &&
3017 (mnt.device.parent.is_on_encrypted_partition())))){
3018
3019 // We could be either directly on LUKS or on LVM-on-LUKS,
3020 // so be sure to get the top-level LUKS UUID.
3021 var crypt_parent = (mnt.device.is_on_encrypted_partition()) ?
3022 mnt.device.parent.uuid : mnt.device.parent.parent.uuid;
3023
3024 // find existing
3025 var entry = CryptTabEntry.find_entry_by_uuid(
3026 crypttab_list, crypt_parent);
3027
3028 // add if missing
3029 if (entry == null){
3030 entry = new CryptTabEntry();
3031 crypttab_list.add(entry);
3032 }
3033
3034 // set custom values
3035 entry.device_uuid = crypt_parent;
3036 entry.mapped_name = "luks-%s".printf(crypt_parent);
3037 entry.keyfile = "none";
3038 entry.options = "luks,nofail";
3039 }
3040 }
3041
3042 log_debug("writing updated file...");
3043
3044 CryptTabEntry.write_file(crypttab_list, crypttab_path, false);
3045
3046 log_msg(_("Updated /etc/crypttab on target device") + ": %s".printf(crypttab_path));
3047
3048 log_debug("Main: fix_crypttab_file(): exit");
3049 }

References _, TeeJee.FileSystem.file_exists(), TeeJee.Logging.log_debug(), TeeJee.Logging.log_msg(), mount_list, and TeeJee.FileSystem.path_combine().

Referenced by restore_other_console(), and restore_other_gui().

◆ fix_fstab_file()

void Main.fix_fstab_file ( string target_path)
inlineprivate

Definition at line 2895 of file Main.vala.

2895 {
2896
2897 log_debug("Main: fix_fstab_file()");
2898
2899 string fstab_path = path_combine(target_path, "etc/fstab");
2900
2901 if (!file_exists(fstab_path)){
2902 log_debug("File not found: %s".printf(fstab_path));
2903 return;
2904 }
2905
2906 var fstab_list = FsTabEntry.read_file(fstab_path);
2907
2908 log_debug("updating entries (1/2)...");
2909
2910 foreach(var mnt in mount_list){
2911 // find existing
2912 var entry = FsTabEntry.find_entry_by_mount_point(fstab_list, mnt.mount_point);
2913
2914 // add if missing
2915 if (entry == null){
2916 entry = new FsTabEntry();
2917 entry.mount_point = mnt.mount_point;
2918 fstab_list.add(entry);
2919 }
2920
2921 //update fstab entry
2922 entry.device_string = "UUID=%s".printf(mnt.device.uuid);
2923 entry.type = mnt.device.fstype;
2924
2925 // fix mount options for non-btrfs device
2926 if (mnt.device.fstype != "btrfs"){
2927 // remove subvol option
2928 entry.remove_option("subvol=%s".printf(entry.subvolume_name()));
2929 }
2930 }
2931
2932 /*
2933 * Remove fstab entries for any system directories that
2934 * the user has not explicitly mapped before restore/clone
2935 * This ensures that the cloned/restored system does not mount
2936 * any devices to system paths that the user has not explicitly specified
2937 * */
2938
2939 log_debug("updating entries(2/2)...");
2940
2941 for(int i = fstab_list.size - 1; i >= 0; i--){
2942 var entry = fstab_list[i];
2943
2944 if (!entry.is_for_system_directory()){ continue; }
2945
2946 var mnt = MountEntry.find_entry_by_mount_point(mount_list, entry.mount_point);
2947 if (mnt == null){
2948 fstab_list.remove(entry);
2949 }
2950 }
2951
2952 // write the updated file
2953
2954 log_debug("writing updated file...");
2955
2956 FsTabEntry.write_file(fstab_list, fstab_path, false);
2957
2958 log_msg(_("Updated /etc/fstab on target device") + ": %s".printf(fstab_path));
2959
2960 // create directories on disk for mount points in /etc/fstab
2961
2962 foreach(var entry in fstab_list){
2963 if (entry.mount_point.length == 0){ continue; }
2964 if (!entry.mount_point.has_prefix("/")){ continue; }
2965
2966 string mount_path = path_combine(
2967 target_path, entry.mount_point);
2968
2969 if (entry.is_comment
2970 || entry.is_empty_line
2971 || (mount_path.length == 0)){
2972
2973 continue;
2974 }
2975
2976 if (!dir_exists(mount_path)){
2977
2978 log_msg("Created mount point on target device: %s".printf(
2979 entry.mount_point));
2980
2981 dir_create(mount_path);
2982 }
2983 }
2984
2985 log_debug("Main: fix_fstab_file(): exit");
2986 }

References _, TeeJee.FileSystem.dir_create(), TeeJee.FileSystem.dir_exists(), TeeJee.FileSystem.file_exists(), MountEntry.find_entry_by_mount_point(), TeeJee.Logging.log_debug(), TeeJee.Logging.log_msg(), mount_list, and TeeJee.FileSystem.path_combine().

Referenced by restore_other_console(), and restore_other_gui().

◆ get_btrfs_version_array()

int?[] Main.get_btrfs_version_array ( )
inlineprivate

Definition at line 392 of file Main.vala.

392 {
393 string stdout;
394 string stderr;
395 int exit_status;
396
397 try {
398 GLib.Process.spawn_command_line_sync(
399 "btrfs --version",
400 out stdout,
401 out stderr,
402 out exit_status
403 );
404 } catch (GLib.Error e) {
405 log_debug("Failed to run btrfs command. Is btrfs-progs installed?");
406 return null;
407 }
408
409 log_debug("Checking btrfs-progs version and determining capabilities...");
410
411 if (exit_status != 0) {
412 log_error("btrfs command failed with exit code %d: %s".printf(exit_status, stderr));
413 return null;
414 }
415
416 string[] lines = stdout.strip().split("\n");
417 if (lines.length == 0) {
418 log_error("No output from btrfs --version");
419 return null;
420 }
421
422 string version_line = null;
423 foreach (string line in lines) {
424 if (line.contains("btrfs-progs")) {
425 version_line = line;
426 break;
427 }
428 }
429
430 if (version_line == null) {
431 log_error("Could not find btrfs-progs version line in output");
432 return null;
433 }
434
435 string version_prefix = "btrfs-progs v";
436 int prefix_index = version_line.index_of(version_prefix);
437 if (prefix_index == -1) {
438 log_error("Could not detect version");
439 return null;
440 }
441
442 string version_string = version_line.substring(prefix_index + version_prefix.length);
443 string[] version_parts = version_string.split(".");
444
445 if (version_parts.length < 2) {
446 log_error("No version components found in: %s".printf(version_string));
447 return null;
448 }
449
450 int[] version = new int[5];
451
452 // version = new int[version_parts.length];
453 for (int i = 0; i < version_parts.length; i++) {
454 version[i] = int.parse(version_parts[i].strip());
455 }
456
457 return version;
458 }

References TeeJee.Logging.log_debug(), and TeeJee.Logging.log_error().

Referenced by check_btrfs_version_capabilities().

◆ get_restore_messages()

void Main.get_restore_messages ( bool formatted,
out string msg_devices,
out string msg_reboot,
out string msg_disclaimer )
inline

Definition at line 2400 of file Main.vala.

2401 {
2402
2403 string msg = "";
2404
2405 log_debug("Main: get_restore_messages()");
2406
2407 // msg_devices -----------------------------------------
2408
2409 if (!formatted){
2410 msg += "\n%s\n%s\n%s\n".printf(
2411 string.nfill(70,'='),
2412 _("Warning").up(),
2413 string.nfill(70,'=')
2414 );
2415 }
2416
2417 msg += _("Data will be modified on following devices:") + "\n\n";
2418
2419 int max_mount = _("Mount").length;
2420 int max_dev = _("Device").length;
2421
2422 foreach(var entry in mount_list){
2423
2424 if (entry.device == null){ continue; }
2425
2426 if (btrfs_mode){
2427
2428 if (entry.subvolume_name().length == 0){ continue; }
2429
2430 if (!App.snapshot_to_restore.subvolumes.has_key(entry.subvolume_name())){ continue; }
2431
2432 if ((entry.subvolume_name() == "@home") && !include_btrfs_home_for_restore){ continue; }
2433 }
2434
2435 string dev_name = entry.device.full_name_with_parent;
2436 if (entry.subvolume_name().length > 0){
2437 dev_name = dev_name + "(%s)".printf(entry.subvolume_name());
2438 }
2439 else if (entry.lvm_name().length > 0){
2440 dev_name = dev_name + "(%s)".printf(entry.lvm_name());
2441 }
2442
2443 if (dev_name.length > max_dev){
2444 max_dev = dev_name.length;
2445 }
2446 if (entry.mount_point.length > max_mount){
2447 max_mount = entry.mount_point.length;
2448 }
2449 }
2450
2451 var txt = ("%%-%ds %%-%ds".printf(max_dev, max_mount))
2452 .printf(_("Device"),_("Mount"));
2453 txt += "\n";
2454
2455 txt += string.nfill(max_dev, '-') + " " + string.nfill(max_mount, '-');
2456 txt += "\n";
2457
2458 foreach(var entry in mount_list){
2459
2460 if (entry.device == null){ continue; }
2461
2462 if (btrfs_mode){
2463
2464 if (entry.subvolume_name().length == 0){ continue; }
2465
2466 if (!App.snapshot_to_restore.subvolumes.has_key(entry.subvolume_name())){ continue; }
2467
2468 if ((entry.subvolume_name() == "@home") && !include_btrfs_home_for_restore){ continue; }
2469 }
2470
2471 string dev_name = entry.device.full_name_with_parent;
2472 if (entry.subvolume_name().length > 0){
2473 dev_name = dev_name + "(%s)".printf(entry.subvolume_name());
2474 }
2475 else if (entry.lvm_name().length > 0){
2476 dev_name = dev_name + "(%s)".printf(entry.lvm_name());
2477 }
2478
2479 txt += ("%%-%ds %%-%ds".printf(max_dev, max_mount)).printf(dev_name, entry.mount_point);
2480
2481 txt += "\n";
2482 }
2483
2484 if (formatted){
2485 msg += "<span size=\"medium\"><tt>%s</tt></span>".printf(txt);
2486 }
2487 else{
2488 msg += "%s\n".printf(txt);
2489 }
2490
2491 msg_devices = msg;
2492
2493 //msg += _("Files will be overwritten on the target device!") + "\n";
2494 //msg += _("If restore fails and you are unable to boot the system, then boot from the Live CD, install BastionGuard Backup, and try to restore again.") + "\n";
2495
2496 // msg_reboot -----------------------
2497
2498 msg = "";
2500 msg += _("Please save your work and close all applications.") + "\n";
2501 msg += _("System will reboot after files are restored.");
2502 }
2503
2504 msg_reboot = msg;
2505
2506 // msg_disclaimer --------------------------------------
2507
2508 msg = "";
2509 if (!formatted){
2510 msg += "\n%s\n%s\n%s\n".printf(
2511 string.nfill(70,'='),
2512 _("Disclaimer").up(),
2513 string.nfill(70,'=')
2514 );
2515 }
2516
2517 msg += _("This software comes without absolutely NO warranty and the author takes no responsibility for any damage arising from the use of this program.");
2518 msg += " " + _("If these terms are not acceptable to you, please do not proceed beyond this point!");
2519
2520 if (!formatted){
2521 msg += "\n";
2522 }
2523
2524 msg_disclaimer = msg;
2525
2526 // display messages in console mode
2527
2528 if (app_mode.length > 0){
2529 log_msg(msg_devices);
2530 log_msg(msg_reboot);
2531 log_msg(msg_disclaimer);
2532 }
2533
2534 log_debug("Main: get_restore_messages(): exit");
2535 }
Main App

References _, App, app_mode, btrfs_mode, include_btrfs_home_for_restore, TeeJee.Logging.log_debug(), TeeJee.Logging.log_msg(), mount_list, restore_current_system, snapshot_to_restore, and Snapshot.subvolumes.

Referenced by AppConsole.confirm_restore(), and RestoreSummaryBox.refresh().

◆ get_space_needed_for_rsync_snapshot()

uint64 Main.get_space_needed_for_rsync_snapshot ( DateTime dt_created)
inlineprivate

Definition at line 1457 of file Main.vala.

1457 {
1458 log_msg(string.nfill(78, '-'));
1459
1460 log_msg("Checking if target drive has enough free space for a snapshot (RSYNC)");
1461 log_msg("Target device: %s, mount path: %s".printf(repo.device.device, repo.mount_path));
1462
1463 string time_stamp = dt_created.format("%Y-%m-%d_%H-%M-%S");
1464 string snapshot_dir = repo.snapshots_path;
1465 string snapshot_name = time_stamp;
1466 string snapshot_path = path_combine(snapshot_dir, snapshot_name);
1467 dir_create(snapshot_path);
1468 string localhost_path = path_combine(snapshot_path, "localhost");
1469 dir_create(localhost_path);
1470
1471 string sys_uuid = (sys_root == null) ? "" : sys_root.uuid;
1472
1473 Snapshot snapshot_to_link = null;
1474
1475 // check if a snapshot was restored recently and use it for linking ---------
1476
1477 try{
1478
1479 string ctl_path = path_combine(snapshot_dir, ".sync-restore");
1480 var f = File.new_for_path(ctl_path);
1481
1482 if (f.query_exists()){
1483
1484 // read snapshot name from file
1485 string snap_path = file_read(ctl_path);
1486 string snap_name = file_basename(snap_path);
1487
1488 // find the snapshot that was restored
1489 foreach(var bak in repo.snapshots){
1490 if ((bak.name == snap_name) && (bak.sys_uuid == sys_uuid)){
1491 // use for linking
1492 snapshot_to_link = bak;
1493 // delete the restore-control-file
1494 f.delete();
1495 break;
1496 }
1497 }
1498 }
1499 }
1500 catch(Error e){
1501 log_error (e.message);
1502 return 0;
1503 }
1504
1505 // get latest snapshot to link if not set -------
1506
1507 if (snapshot_to_link == null){
1508 snapshot_to_link = repo.get_latest_snapshot("", sys_uuid);
1509 }
1510
1511 string link_from_path = "";
1512 if (snapshot_to_link != null){
1513 log_msg("Linking from snapshot: %s".printf(snapshot_to_link.name));
1514 link_from_path = "%s/localhost/".printf(snapshot_to_link.path);
1515 }
1516
1517 // save exclude list ----------------
1518
1519 string? exclude_from_file = save_exclude_list_for_backup(snapshot_path);
1520
1521 if (null == exclude_from_file){
1522 log_error("Failed to save exclude list");
1523 return 0;
1524 }
1525
1526 progress_text = _("Calculating required disk space...");
1528
1530
1531 space_check_task.source_path = "";
1532 space_check_task.dest_path = snapshot_path + "/localhost/";
1533 space_check_task.link_from_path = link_from_path;
1534 space_check_task.exclude_from_file = exclude_from_file;
1535 space_check_task.prg_count_total = Main.first_snapshot_count;
1536
1537 space_check_task.relative = true;
1538 space_check_task.verbose = true;
1539 space_check_task.delete_extra = true;
1540 space_check_task.delete_excluded = true;
1541 space_check_task.delete_after = false;
1542
1544
1545 while (space_check_task.status == AppStatus.RUNNING){
1546 sleep(1000);
1547 gtk_do_events();
1548
1549 stdout.flush();
1550 }
1551
1552 var total_size = space_check_task.total_size;
1553 space_check_task = null;
1554 return total_size;
1555 }
RsyncSpaceCheckTask space_check_task
Definition Main.vala:162

References _, Device.device, SnapshotRepo.device, TeeJee.FileSystem.dir_create(), Error, AsyncTask.execute(), TeeJee.FileSystem.file_basename(), TeeJee.FileSystem.file_read(), SnapshotRepo.get_latest_snapshot(), TeeJee.GtkHelper.gtk_do_events(), TeeJee.Logging.log_error(), TeeJee.Logging.log_msg(), Main(), SnapshotRepo.mount_path, Snapshot.name, Snapshot.path, TeeJee.FileSystem.path_combine(), progress_text, repo, RsyncSpaceCheckTask.RsyncSpaceCheckTask(), save_exclude_list_for_backup(), TeeJee.System.sleep(), SnapshotRepo.snapshots, SnapshotRepo.snapshots_path, space_check_task, AsyncTask.status, sys_root, RsyncSpaceCheckTask.total_size, and Device.uuid.

Referenced by create_snapshot_for_tag().

◆ import_timeshift_config_if_available()

bool Main.import_timeshift_config_if_available ( )
inline

Definition at line 3421 of file Main.vala.

3421 {
3422
3423 log_debug("Main: import_timeshift_config_if_available()");
3424
3425 string[] candidate_paths = {
3426 /* Prima Timeshift legacy */
3427 "/etc/timeshift/timeshift.json",
3428 "/etc/timeshift.json",
3429
3430 /* Poi eventuale config BastionGuard legacy */
3431 "/etc/bastionguard-backup/bastionguard-backup.json",
3432 "/etc/bastionguard-backup.json"
3433 };
3434
3435 string src_path = "";
3436 bool importing_legacy_timeshift = false;
3437
3438 foreach (string path in candidate_paths) {
3439 if (!file_exists(path)) {
3440 continue;
3441 }
3442
3443 /* evita di "importare" la stessa config target */
3444 if (path == this.app_conf_path) {
3445 continue;
3446 }
3447
3448 src_path = path;
3449
3450 if ((path == "/etc/timeshift/timeshift.json") ||
3451 (path == "/etc/timeshift.json")) {
3452 importing_legacy_timeshift = true;
3453 }
3454 break;
3455 }
3456
3457 if (src_path.length == 0) {
3458 log_debug("No Timeshift/BastionGuard config found for import");
3459 return false;
3460 }
3461
3462 if (importing_legacy_timeshift) {
3463 log_msg(_("Found legacy Timeshift config") + ": %s".printf(src_path));
3464 }
3465 else {
3466 log_msg(_("Found BastionGuard config") + ": %s".printf(src_path));
3467 }
3468
3469 var parser = new Json.Parser();
3470 try {
3471 parser.load_from_file(src_path);
3472 }
3473 catch (Error e) {
3474 log_error("Failed to parse config: " + e.message);
3475 return false;
3476 }
3477
3478 Json.Node? node = parser.get_root();
3479 Json.Object config = node?.get_object() ?? new Json.Object();
3480
3481 backup_uuid = json_get_string(config, "backup_device_uuid", backup_uuid);
3482 backup_parent_uuid = json_get_string(config, "parent_device_uuid", backup_parent_uuid);
3483
3484 btrfs_mode = json_get_bool(config, "btrfs_mode", btrfs_mode);
3485
3486 if (config.has_member("include_btrfs_home")) {
3488 json_get_bool(config, "include_btrfs_home", include_btrfs_home_for_backup);
3489 }
3490 else {
3492 json_get_bool(config, "include_btrfs_home_for_backup", include_btrfs_home_for_backup);
3493 }
3494
3496 json_get_bool(config, "include_btrfs_home_for_restore", include_btrfs_home_for_restore);
3497
3499 json_get_bool(config, "stop_cron_emails", stop_cron_emails);
3500
3501 schedule_monthly = json_get_bool(config, "schedule_monthly", schedule_monthly);
3502 schedule_weekly = json_get_bool(config, "schedule_weekly", schedule_weekly);
3503 schedule_daily = json_get_bool(config, "schedule_daily", schedule_daily);
3504 schedule_hourly = json_get_bool(config, "schedule_hourly", schedule_hourly);
3505 schedule_boot = json_get_bool(config, "schedule_boot", schedule_boot);
3506
3507 count_monthly = json_get_int(config, "count_monthly", count_monthly);
3508 count_weekly = json_get_int(config, "count_weekly", count_weekly);
3509 count_daily = json_get_int(config, "count_daily", count_daily);
3510 count_hourly = json_get_int(config, "count_hourly", count_hourly);
3511 count_boot = json_get_int(config, "count_boot", count_boot);
3512
3513 date_format = json_get_string(config, "date_format", date_format_default);
3514
3515 Main.first_snapshot_size =
3516 json_get_uint64(config, "snapshot_size", Main.first_snapshot_size);
3517 Main.first_snapshot_count =
3518 (int64) json_get_uint64(config, "snapshot_count", Main.first_snapshot_count);
3519
3520 exclude_list_user.clear();
3521 if (config.has_member("exclude")) {
3522 foreach (Json.Node jnode in config.get_array_member("exclude").get_elements()) {
3523 string path = jnode.get_string();
3524
3525 if (!exclude_list_user.contains(path)
3526 && !exclude_list_default.contains(path)
3527 && !exclude_list_home.contains(path)) {
3528
3529 exclude_list_user.add(path);
3530 }
3531 }
3532 }
3533
3534 exclude_app_names.clear();
3535 if (config.has_member("exclude-apps")) {
3536 foreach (Json.Node jnode in config.get_array_member("exclude-apps").get_elements()) {
3537 string name = jnode.get_string();
3538 if (!exclude_app_names.contains(name)) {
3539 exclude_app_names.add(name);
3540 }
3541 }
3542 }
3543
3544 /* dopo un import non siamo più in first-run puro */
3545 first_run = true;
3546
3547 /* assicura che la directory target esista */
3548 string conf_dir = File.new_for_path(this.app_conf_path).get_parent().get_path();
3549 if (!FileUtils.test(conf_dir, FileTest.IS_DIR)) {
3550 DirUtils.create_with_parents(conf_dir, 0755);
3551 }
3552
3554
3555 if (importing_legacy_timeshift) {
3556 log_msg(_("Imported Timeshift settings into BastionGuard Backup"));
3557 }
3558 else {
3559 log_msg(_("Imported BastionGuard settings"));
3560 }
3561
3562 return true;
3563 }
bool first_run
Definition Main.vala:47
int count_monthly
Definition Main.vala:92
string app_conf_path
Definition Main.vala:44
string date_format
Definition Main.vala:130
int count_hourly
Definition Main.vala:95
string backup_uuid
Definition Main.vala:49
string backup_parent_uuid
Definition Main.vala:50
int count_boot
Definition Main.vala:96
const string date_format_default
Definition Main.vala:131
int count_weekly
Definition Main.vala:93
int count_daily
Definition Main.vala:94
uint64 json_get_uint64(Json.Object jobj, string member, uint64 def_value)
string json_get_string(Json.Object jobj, string member, string def_value)
int json_get_int(Json.Object jobj, string member, int def_value)
bool json_get_bool(Json.Object jobj, string member, bool def_value)

References _, backup_parent_uuid, backup_uuid, btrfs_mode, count_boot, count_daily, count_hourly, count_monthly, count_weekly, date_format, date_format_default, Error, exclude_app_names, exclude_list_default, exclude_list_home, exclude_list_user, TeeJee.FileSystem.file_exists(), first_run, first_snapshot_count, first_snapshot_size, include_btrfs_home_for_backup, include_btrfs_home_for_restore, TeeJee.JsonHelper.json_get_bool(), TeeJee.JsonHelper.json_get_int(), TeeJee.JsonHelper.json_get_string(), TeeJee.JsonHelper.json_get_uint64(), TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), TeeJee.Logging.log_msg(), Main(), save_app_config(), schedule_boot, schedule_daily, schedule_hourly, schedule_monthly, schedule_weekly, and stop_cron_emails.

Referenced by SetupWizardWindow.run_timeshift_import().

◆ init_boot_options()

void Main.init_boot_options ( )
inline

Definition at line 2265 of file Main.vala.

2265 {
2266
2267 var grub_dev = dst_root;
2268 if(grub_dev != null){
2269 grub_device = grub_dev.device;
2270 }
2271
2272 while ((grub_dev != null) && grub_dev.has_parent()){
2273 grub_dev = grub_dev.parent;
2274 grub_device = grub_dev.device;
2275 }
2276
2277 if (mirror_system){
2278 // bootloader must be re-installed
2279 reinstall_grub2 = true;
2280 update_initramfs = true;
2281 update_grub = true;
2282 }
2283 else{
2284 if (snapshot_to_restore.distro.dist_id == "fedora"){
2285 // grub2-install should never be run on EFI fedora systems
2286 reinstall_grub2 = false;
2287 update_initramfs = false;
2288 update_grub = true;
2289 }
2290 else{
2291 reinstall_grub2 = true;
2292 update_initramfs = false;
2293 update_grub = true;
2294 }
2295 }
2296 }
Device? dst_root
Definition Main.vala:1948
LinuxDistro distro
Definition Snapshot.vala:52

References LinuxDistro.dist_id, Snapshot.distro, dst_root, grub_device, mirror_system, reinstall_grub2, snapshot_to_restore, update_grub, and update_initramfs.

Referenced by RestoreDeviceBox.add_device_combo(), init_mount_list(), and RestoreDeviceBox.refresh().

◆ init_mount_list()

void Main.init_mount_list ( )
inline

Definition at line 2075 of file Main.vala.

2075 {
2076
2077 log_debug("Main: init_mount_list()");
2078
2079 mount_list.clear();
2080
2081 Gee.ArrayList<FsTabEntry> fstab_list = null;
2082 Gee.ArrayList<CryptTabEntry> crypttab_list = null;
2083
2084 if (mirror_system){
2085 string fstab_path = "/etc/fstab";
2086 fstab_list = FsTabEntry.read_file(fstab_path);
2087 string cryttab_path = "/etc/crypttab";
2088 crypttab_list = CryptTabEntry.read_file(cryttab_path);
2089 }
2090 else{
2091 fstab_list = snapshot_to_restore.fstab_list;
2092 crypttab_list = snapshot_to_restore.cryttab_list;
2093 }
2094
2095 bool root_found = false;
2096 bool boot_found = false;
2097 bool home_found = false;
2098 dst_root = null;
2099
2100 foreach(var fs_entry in fstab_list){
2101
2102 // skip mounting for non-system devices ----------
2103
2104 if (!fs_entry.is_for_system_directory()){
2105 continue;
2106 }
2107
2108 // skip mounting excluded devices -----------------------
2109
2110 string p1 = "%s/*".printf(fs_entry.mount_point);
2111 string p2 = "%s/**".printf(fs_entry.mount_point);
2112 string p3 = "%s/***".printf(fs_entry.mount_point);
2113
2114 if (exclude_list_default.contains(p1) || exclude_list_user.contains(p1)){
2115 continue;
2116 }
2117 else if (exclude_list_default.contains(p2) || exclude_list_user.contains(p2)){
2118 continue;
2119 }
2120 else if (exclude_list_default.contains(p3) || exclude_list_user.contains(p3)){
2121 continue;
2122 }
2123
2124 // find device by name or uuid --------------------------
2125
2126 Device dev_fstab = null;
2127 if (fs_entry.device_uuid.length > 0){
2128 dev_fstab = Device.get_device_by_uuid(fs_entry.device_uuid);
2129 }
2130 else{
2131 dev_fstab = Device.get_device_by_name(fs_entry.device_string);
2132 }
2133
2134 if (dev_fstab == null){
2135
2136 /*
2137 Check if the device mentioned in fstab entry is a mapped device.
2138 If it is, then try finding the parent device which may be available on the current system.
2139 Prompt user to unlock it if found.
2140
2141 Note:
2142 Mapped name may be different on running system, or it may be same.
2143 Since it is not reliable, we will try to identify the parent instead of the mapped device.
2144 */
2145
2146 if (fs_entry.device_string.has_prefix("/dev/mapper/")){
2147
2148 string mapped_name = fs_entry.device_string.replace("/dev/mapper/","");
2149
2150 foreach(var crypt_entry in crypttab_list){
2151
2152 if (crypt_entry.mapped_name == mapped_name){
2153
2154 // we found the entry for the mapped device
2155 fs_entry.device_string = crypt_entry.device_string;
2156
2157 if (fs_entry.device_uuid.length > 0){
2158
2159 // we have the parent's uuid. get the luks device and prompt user to unlock it.
2160 var dev_luks = Device.get_device_by_uuid(fs_entry.device_uuid);
2161
2162 if (dev_luks != null){
2163
2164 string msg_out, msg_err;
2165 var dev_unlocked = Device.luks_unlock(
2166 dev_luks, "", "", parent_window, out msg_out, out msg_err);
2167
2168 if (dev_unlocked != null){
2169 dev_fstab = dev_unlocked;
2171 }
2172 else{
2173 dev_fstab = dev_luks; // map to parent
2174 }
2175 }
2176 }
2177 else{
2178 // nothing to do: we don't have the parent's uuid
2179 }
2180
2181 break;
2182 }
2183 }
2184 }
2185 }
2186
2187 if (dev_fstab != null){
2188
2189 log_debug("added: dev: %s, path: %s, options: %s".printf(
2190 dev_fstab.device, fs_entry.mount_point, fs_entry.options));
2191
2192 mount_list.add(new MountEntry(dev_fstab, fs_entry.mount_point, fs_entry.options));
2193
2194 if (fs_entry.mount_point == "/"){
2195 dst_root = dev_fstab;
2196 }
2197 }
2198 else{
2199 log_debug("missing: dev: %s, path: %s, options: %s".printf(
2200 fs_entry.device_string, fs_entry.mount_point, fs_entry.options));
2201
2202 mount_list.add(new MountEntry(null, fs_entry.mount_point, fs_entry.options));
2203 }
2204
2205 if (fs_entry.mount_point == "/"){
2206 root_found = true;
2207 }
2208 if (fs_entry.mount_point == "/boot"){
2209 boot_found = true;
2210 }
2211 if (fs_entry.mount_point == "/home"){
2212 home_found = true;
2213 }
2214 }
2215
2216 if (!root_found){
2217 log_debug("added null entry: /");
2218 mount_list.add(new MountEntry(null, "/", "")); // add root entry
2219 }
2220
2221 if (!boot_found){
2222 log_debug("added null entry: /boot");
2223 mount_list.add(new MountEntry(null, "/boot", "")); // add boot entry
2224 }
2225
2226 if (!home_found){
2227 log_debug("added null entry: /home");
2228 mount_list.add(new MountEntry(null, "/home", "")); // add home entry
2229 }
2230
2231 /*
2232 While cloning the system, /boot is the only mount point that
2233 we will leave unchanged (to avoid encrypted systems from breaking).
2234 All other mounts like /home will be defaulted to target device
2235 (to prevent the "cloned" system from using the original device)
2236 */
2237
2238 if (mirror_system){
2239 dst_root = null;
2240 foreach (var entry in mount_list){
2241 // user should select another device
2242 entry.device = null;
2243 }
2244 }
2245
2246 foreach(var mnt in mount_list){
2247 if (mnt.device != null){
2248 log_debug("Entry: %s -> %s".printf(mnt.device.device, mnt.mount_point));
2249 }
2250 else{
2251 log_debug("Entry: null -> %s".printf(mnt.mount_point));
2252 }
2253 }
2254
2255 // sort - parent mountpoints will be placed above children
2256 mount_list.sort((a,b) => {
2257 return strcmp(a.mount_point, b.mount_point);
2258 });
2259
2260 init_boot_options(); // boot options depend on the mount list
2261
2262 log_debug("Main: init_mount_list(): exit");
2263 }
static ? Device get_device_by_uuid(string uuid)
Definition Device.vala:1081
static ? Device get_device_by_name(string file_name)
Definition Device.vala:1086
void init_boot_options()
Definition Main.vala:2265
MountEntry(Device? device, string mount_point, string mount_options)
Gee.ArrayList< CryptTabEntry > cryttab_list
Definition Snapshot.vala:48
Gee.ArrayList< FsTabEntry > fstab_list
Definition Snapshot.vala:47

References Snapshot.cryttab_list, Device.device, dst_root, exclude_list_default, exclude_list_user, Snapshot.fstab_list, Device.get_device_by_name(), Device.get_device_by_uuid(), init_boot_options(), TeeJee.Logging.log_debug(), Device.luks_unlock(), mirror_system, mount_list, MountEntry.MountEntry(), parent_window, snapshot_to_restore, and update_partitions().

Referenced by RestoreDeviceBox.create_device_selection_options(), AppConsole.init_mounts(), and MainWindow.restore().

◆ initialize()

void Main.initialize ( )
inline

Definition at line 337 of file Main.vala.

337 {
338
340 }
void initialize_repo()
Definition Main.vala:3727

References initialize_repo().

Referenced by AppConsole.main(), and AppGtk.main().

◆ initialize_repo()

void Main.initialize_repo ( )
inline

Definition at line 3727 of file Main.vala.

3727 {
3728
3729 log_debug("Main: initialize_repo()");
3730
3731 log_debug("backup_uuid=%s".printf(backup_uuid));
3732 log_debug("backup_parent_uuid=%s".printf(backup_parent_uuid));
3733
3734 // use system disk as snapshot device in btrfs mode for backup
3735 if (((app_mode == "backup")||((app_mode == "ondemand"))) && btrfs_mode){
3736 if (sys_root != null){
3737 log_msg("Using system disk as snapshot device for creating snapshots in BTRFS mode");
3738 if (cmd_backup_device.length > 0){
3739 log_msg(_("Option --snapshot-device should not be specified for creating snapshots in BTRFS mode"));
3740 }
3741 repo = new SnapshotRepo.from_device(sys_root, parent_window, btrfs_mode);
3742 }
3743 else{
3744 log_error("System disk not found!");
3745 exit_app(1);
3746 }
3747 }
3748 // initialize repo using command line parameter if specified
3749 else if (cmd_backup_device.length > 0){
3750 var cmd_dev = Device.get_device_by_name(cmd_backup_device);
3751 if (cmd_dev != null){
3752 log_debug("Using snapshot device specified as command argument: %s".printf(cmd_backup_device));
3753 repo = new SnapshotRepo.from_device(cmd_dev, parent_window, btrfs_mode);
3754 // TODO: move this code to main window
3755 }
3756 else{
3757 log_error(_("Device not found") + ": '%s'".printf(cmd_backup_device));
3758 exit_app(1);
3759 }
3760 }
3761 // select default device for first run mode
3762 else if (first_run && (backup_uuid.length == 0)){
3763
3765
3766 if ((repo != null) && (repo.device != null)){
3767 log_msg(_("Selected default snapshot device") + ": %s".printf(repo.device.device));
3768 }
3769 }
3770 else {
3771 log_debug("Setting snapshot device from config file");
3772
3773 // find devices from uuid
3774 Device dev = null;
3775 Device dev_parent = null;
3776 if (backup_uuid != null && backup_uuid.length > 0){
3777 dev = Device.get_device_by_uuid(backup_uuid);
3778 }
3779 if (backup_parent_uuid != null && backup_parent_uuid.length > 0){
3780 dev_parent = Device.get_device_by_uuid(backup_parent_uuid);
3781 }
3782
3783 // try unlocking encrypted parent
3784 if ((dev_parent != null) && dev_parent.is_encrypted_partition() && !dev_parent.has_children()){
3785 log_debug("Snapshot device is on an encrypted partition");
3787 }
3788 // try device
3789 else if (dev != null){
3790 log_debug("repo: creating from uuid");
3791 repo = new SnapshotRepo.from_uuid(backup_uuid, parent_window, btrfs_mode);
3792 }
3793 // try system disk
3794 /*else {
3795 log_debug("Could not find device with UUID" + ": %s".printf(backup_uuid));
3796 if (sys_root != null){
3797 log_debug("Using system disk as snapshot device");
3798 repo = new SnapshotRepo.from_device(sys_root, parent_window, btrfs_mode);
3799 }
3800 else{
3801 log_debug("System disk not found");
3802 repo = new SnapshotRepo.from_null();
3803 }
3804 }*/
3805 }
3806
3807 /* Note: In command-line mode, user will be prompted for backup device */
3808
3809 /* The backup device specified in config file will be mounted at this point if:
3810 * 1) app is running in GUI mode, OR
3811 * 2) app is running command mode without backup device argument
3812 * */
3813
3814 log_debug("Main: initialize_repo(): exit");
3815 }
string cmd_backup_device
Definition Main.vala:147
void try_select_default_device_for_backup(Gtk.Window? parent_win)
Definition Main.vala:4110
SnapshotRepo. from_device(Device dev, Gtk.Window? parent_win, bool btrfs_repo)
SnapshotRepo. from_uuid(string uuid, Gtk.Window? parent_win, bool btrfs_repo)

References _, app_mode, backup_parent_uuid, backup_uuid, btrfs_mode, cmd_backup_device, Device.device, SnapshotRepo.device, exit_app(), first_run, SnapshotRepo.from_device(), SnapshotRepo.from_uuid(), Device.get_device_by_name(), Device.get_device_by_uuid(), Device.has_children(), Device.is_encrypted_partition(), TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), TeeJee.Logging.log_msg(), parent_window, repo, sys_root, and try_select_default_device_for_backup().

Referenced by initialize(), and SetupWizardWindow.run_timeshift_import().

◆ live_system()

bool Main.live_system ( )
inline

Definition at line 1058 of file Main.vala.

1058 {
1059 // In modalità recovery vogliamo tutte le funzioni attive
1060 // anche se il sistema è stato avviato con boot=live
1061 if (app_mode == "recovery") {
1062 return false;
1063 }
1064
1065 /* Initialize once block */
1066 if (_live_system == -1) {
1067 var cmdline = file_read("/proc/cmdline");
1068
1069 if (cmdline.contains("boot=casper") || cmdline.contains("boot=live")) {
1070 log_msg ("Live Session detected, backup is disabled.");
1071 _live_system = 1;
1072 } else {
1073 _live_system = 0;
1074 }
1075 }
1076
1077 return (_live_system == 1);
1078 }
int _live_system
Definition Main.vala:169

References _live_system, app_mode, TeeJee.FileSystem.file_read(), and TeeJee.Logging.log_msg().

Referenced by BackupDeviceBox.check_backup_location(), cron_job_update(), estimate_system_size(), SetupWizardWindow.go_next(), MainWindow.MainWindow(), MainWindow.on_close_request(), and AppConsole.start_application().

◆ load_app_config()

void Main.load_app_config ( )
inline

Definition at line 3564 of file Main.vala.

3564 {
3565
3566 log_debug("Main: load_app_config()");
3567
3568 // check if first run -----------------------
3569
3570 var f = File.new_for_path(this.app_conf_path);
3571
3572 if (!f.query_exists()) {
3573
3575 // move old file
3577 }
3579 // /etc/bastionguard-backup might not pre-exist when sysconfdir is not /etc
3582 }
3583 // copy default file
3585 }
3586 }
3587
3588 // load settings from config file --------------------------
3589
3590 var parser = new Json.Parser();
3591 try{
3592 parser.load_from_file(this.app_conf_path);
3593 } catch (Error e) {
3594 log_error (e.message);
3595 }
3596 Json.Node? node = parser.get_root();
3597
3598 // make sure object is always set
3599 Json.Object config = node?.get_object() ?? new Json.Object();
3600
3601 bool do_first_run = json_get_bool(config, "do_first_run", false); // false as default
3602
3603 btrfs_mode = json_get_bool(config, "btrfs_mode", false); // false as default
3604
3605 if (do_first_run){
3607 }
3608
3609 if (config.has_member("include_btrfs_home")){
3611 }
3612 else{
3613 include_btrfs_home_for_backup = json_get_bool(config, "include_btrfs_home_for_backup", include_btrfs_home_for_backup);
3614 }
3615
3616 include_btrfs_home_for_restore = json_get_bool(config, "include_btrfs_home_for_restore", include_btrfs_home_for_restore);
3617 stop_cron_emails = json_get_bool(config, "stop_cron_emails", stop_cron_emails);
3618
3619 if (cmd_btrfs_mode != null){
3620 btrfs_mode = cmd_btrfs_mode; //override
3621 }
3622
3623 backup_uuid = json_get_string(config,"backup_device_uuid", backup_uuid);
3624 backup_parent_uuid = json_get_string(config,"parent_device_uuid", backup_parent_uuid);
3625
3626 this.schedule_monthly = json_get_bool(config,"schedule_monthly",schedule_monthly);
3627 this.schedule_weekly = json_get_bool(config,"schedule_weekly",schedule_weekly);
3628 this.schedule_daily = json_get_bool(config,"schedule_daily",schedule_daily);
3629 this.schedule_hourly = json_get_bool(config,"schedule_hourly",schedule_hourly);
3630 this.schedule_boot = json_get_bool(config,"schedule_boot",schedule_boot);
3631
3632 this.count_monthly = json_get_int(config,"count_monthly",count_monthly);
3633 this.count_weekly = json_get_int(config,"count_weekly",count_weekly);
3634 this.count_daily = json_get_int(config,"count_daily",count_daily);
3635 this.count_hourly = json_get_int(config,"count_hourly",count_hourly);
3636 this.count_boot = json_get_int(config,"count_boot",count_boot);
3637
3638 this.date_format = json_get_string(config, "date_format", date_format_default);
3639
3640 Main.first_snapshot_size = json_get_uint64(config,"snapshot_size", Main.first_snapshot_size);
3641
3642 Main.first_snapshot_count = (int64) json_get_uint64(config,"snapshot_count", Main.first_snapshot_count);
3643
3644 exclude_list_user.clear();
3645
3646 if (config.has_member ("exclude")){
3647
3648 foreach (Json.Node jnode in config.get_array_member ("exclude").get_elements()) {
3649
3650 string path = jnode.get_string();
3651
3652 if (!exclude_list_user.contains(path)
3653 && !exclude_list_default.contains(path)
3654 && !exclude_list_home.contains(path)){
3655
3656 exclude_list_user.add(path);
3657 }
3658 }
3659 }
3660
3661 exclude_app_names.clear();
3662
3663 if (config.has_member ("exclude-apps")){
3664
3665 var apps = config.get_array_member("exclude-apps");
3666
3667 foreach (Json.Node jnode in apps.get_elements()) {
3668
3669 string name = jnode.get_string();
3670
3671 if (!exclude_app_names.contains(name)){
3672 exclude_app_names.add(name);
3673 }
3674 }
3675 }
3676
3677 if ((app_mode == "")||(LOG_DEBUG)){
3678 log_msg(_("App config loaded") + ": %s".printf(this.app_conf_path));
3679 }
3680
3681 // Se backup_uuid è ancora vuoto, leggi il fallback dalla config BastionGuardBackup legacy
3682 if (backup_uuid.length == 0) {
3683 string[] ts_configs = {
3684 "/etc/bastionguard-backup/bastionguard-backup.json",
3685 "/etc/bastionguard-backup.json",
3686 "/etc/timeshift/timeshift.json",
3687 "/etc/timeshift.json"
3688 };
3689 foreach (string ts_path in ts_configs) {
3690 if (!file_exists(ts_path)) continue;
3691 try {
3692 var ts_parser = new Json.Parser();
3693 ts_parser.load_from_file(ts_path);
3694 var ts_cfg = ts_parser.get_root()?.get_object();
3695 if (ts_cfg != null) {
3696 string uuid = json_get_string(ts_cfg, "backup_device_uuid", "");
3697 if (uuid.length > 0) {
3698 backup_uuid = uuid;
3699 log_msg("BastionGuardBackup fallback: backup_uuid = " + uuid);
3700 }
3701 }
3702 } catch {}
3703 if (backup_uuid.length > 0) break;
3704 }
3705 }
3706 }
string app_conf_path_old
Definition Main.vala:45
string app_conf_path_default
Definition Main.vala:46
bool? cmd_btrfs_mode
Definition Main.vala:154
void set_first_run_flag()
Definition Main.vala:3708
string file_parent(string file_path)
bool file_copy(string src_file, string dest_file)
void file_move(string src_file, string dest_file)

References _, app_conf_path, app_conf_path_default, app_conf_path_old, app_mode, backup_parent_uuid, backup_uuid, btrfs_mode, cmd_btrfs_mode, count_boot, count_daily, count_hourly, count_monthly, count_weekly, date_format_default, TeeJee.FileSystem.dir_create(), TeeJee.FileSystem.dir_exists(), Error, exclude_app_names, exclude_list_default, exclude_list_home, exclude_list_user, TeeJee.FileSystem.file_copy(), TeeJee.FileSystem.file_exists(), TeeJee.FileSystem.file_move(), TeeJee.FileSystem.file_parent(), first_snapshot_count, first_snapshot_size, include_btrfs_home_for_backup, include_btrfs_home_for_restore, TeeJee.JsonHelper.json_get_bool(), TeeJee.JsonHelper.json_get_int(), TeeJee.JsonHelper.json_get_string(), TeeJee.JsonHelper.json_get_uint64(), TeeJee.Logging.LOG_DEBUG, TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), TeeJee.Logging.log_msg(), Main(), schedule_boot, schedule_daily, schedule_hourly, schedule_monthly, schedule_weekly, set_first_run_flag(), and stop_cron_emails.

Referenced by Main().

◆ mount_target_devices()

bool Main.mount_target_devices ( Gtk.Window? parent_win = null)
inline

Definition at line 3910 of file Main.vala.

3910 {
3911 /* Note:
3912 * Target device will be mounted explicitly to /run/bastionguard-backup/<pid>/restore
3913 * Existing mount points are not used since we need to mount other devices in sub-directories
3914 * */
3915
3916 log_debug("mount_target_device()");
3917
3918 if (dst_root == null){
3919 return false;
3920 }
3921
3922 //check and create restore mount point for restore
3923 mount_point_restore = mount_point_app + "/restore";
3925
3926 /*var already_mounted = false;
3927 var dev_mounted = Device.get_device_by_path(mount_point_restore);
3928 if ((dev_mounted != null)
3929 && (dev_mounted.uuid == dst_root.uuid)){
3930
3931 foreach(var mp in dev_mounted.mount_points){
3932 if ((mp.mount_point == mount_point_restore)
3933 && (mp.mount_options == "subvol=@")){
3934
3935 = true;
3936 return; //already_mounted
3937 }
3938 }
3939 }*/
3940
3941 // unmount
3943
3944 // mount root device
3945 if (dst_root.fstype == "btrfs"){
3946
3947 //check subvolume layout
3948
3949 bool supported = check_btrfs_layout(dst_root, dst_home, false);
3950
3951 if (!supported && snapshot_to_restore.has_subvolumes()){
3952 string msg = _("The target partition has an unsupported subvolume layout.") + "\n";
3953 msg += _("Only ubuntu-type layouts with @ and @home subvolumes are currently supported.");
3954
3955 if (app_mode == ""){
3956 string title = _("Unsupported Subvolume Layout");
3957 gtk_messagebox(title, msg, null, true);
3958 }
3959 else{
3960 log_error("\n" + msg);
3961 }
3962
3963 return false;
3964 }
3965 }
3966
3967 // mount all devices
3968 foreach (var mnt in mount_list) {
3969
3970 if (mnt.device == null){
3971 continue;
3972 }
3973
3974 // unlock encrypted device
3975 if (mnt.device.is_encrypted_partition()){
3976
3977 // check if unlocked
3978 if (mnt.device.has_children()){
3979 mnt.device = mnt.device.children[0];
3980 }
3981 else{
3982 // prompt user
3983 string msg_out, msg_err;
3984
3985 var dev_unlocked = Device.luks_unlock(
3986 mnt.device, "", "", parent_win, out msg_out, out msg_err);
3987
3988 //exit if not found
3989 if (dev_unlocked == null){
3990 return false;
3991 }
3992 else{
3993 mnt.device = dev_unlocked;
3994 }
3995 }
3996 }
3997
3998 string mount_options = "";
3999
4000 if (mnt.device.fstype == "btrfs"){
4001 if (mnt.mount_point == "/"){
4002 mount_options = "subvol=@";
4003 }
4005 if (mnt.mount_point == "/home"){
4006 mount_options = "subvol=@home";
4007 }
4008 }
4009 }
4010
4011 if (!Device.mount(mnt.device.uuid, mount_point_restore + mnt.mount_point, mount_options)){
4012 return false;
4013 }
4014 }
4015
4016 return true;
4017 }
bool check_btrfs_layout(Device? dev_root, Device? dev_home, bool unlock)
Definition Main.vala:507
string mount_point_restore
Definition Main.vala:81
Device? dst_home
Definition Main.vala:2005
bool has_subvolumes()

References _, app_mode, check_btrfs_layout(), TeeJee.FileSystem.dir_create(), dst_home, dst_root, Device.fstype, Snapshot.has_subvolumes(), include_btrfs_home_for_restore, TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), Device.luks_unlock(), Device.mount(), mount_list, mount_point_app, mount_point_restore, snapshot_to_restore, and unmount_target_device().

Referenced by RestoreDeviceBox.check_and_mount_devices(), and AppConsole.restore_snapshot().

◆ parse_some_arguments()

void Main.parse_some_arguments ( string[] args)
inlineprivate

Definition at line 537 of file Main.vala.

537 {
538
539 for (int k = 1; k < args.length; k++) // Oth arg is app path
540 {
541 switch (args[k].down()){
542 case "--debug":
543 LOG_COMMANDS = true;
544 LOG_DEBUG = true;
545 break;
546
547 case "--btrfs":
548 btrfs_mode = true;
550 break;
551
552 case "--rsync":
553 btrfs_mode = false;
555 break;
556
557 case "--check":
558 app_mode = "backup";
559 break;
560
561 case "--delete":
562 app_mode = "delete";
563 break;
564
565 case "--delete-all":
566 app_mode = "delete-all";
567 break;
568
569 case "--restore":
570 app_mode = "restore";
571 break;
572
573 case "--clone":
574 app_mode = "restore";
575 break;
576
577 case "--create":
578 app_mode = "ondemand";
579 break;
580
581 case "--list":
582 case "--list-snapshots":
583 app_mode = "list-snapshots";
584 break;
585
586 case "--list-devices":
587 app_mode = "list-devices";
588 break;
589 }
590 }
591 }

References app_mode, btrfs_mode, cmd_btrfs_mode, TeeJee.Logging.LOG_COMMANDS, and TeeJee.Logging.LOG_DEBUG.

Referenced by Main().

◆ progressCallback()

delegate void Main.progressCallback ( )

Referenced by estimate_system_size().

◆ query_subvolume_id()

bool Main.query_subvolume_id ( string subvol_name)
inline

Definition at line 4288 of file Main.vala.

4288 {
4289
4290 log_debug("query_subvolume_id():%s".printf(subvol_name));
4291
4292 string cmd = "";
4293 string std_out;
4294 string std_err;
4295 int ret_val;
4296
4297 cmd = "btrfs subvolume list '%s'".printf(repo.mount_paths[subvol_name]);
4298 log_debug(cmd);
4299 ret_val = exec_sync(cmd, out std_out, out std_err);
4300 if (ret_val != 0){
4301 log_error (std_err);
4302 log_error(_("btrfs returned an error") + ": %d".printf(ret_val));
4303 log_error(_("Failed to query subvolume list"));
4304 return false;
4305 }
4306
4307 /* Sample Output:
4308 *
4309 ID 257 gen 56 top level 5 path bastionguard-backup-btrfs/snapshots/2014-09-26_23-34-08/@
4310 ID 258 gen 52 top level 5 path bastionguard-backup-btrfs/snapshots/2014-09-26_23-34-08/@home
4311 * */
4312
4313 foreach(string line in std_out.split("\n")){
4314 if (line == null) { continue; }
4315
4316 string[] parts = line.split(" ");
4317 if (parts.length < 2) { continue; }
4318
4319 Subvolume subvol = null;
4320
4321 if ((sys_subvolumes.size > 0) && line.has_suffix(sys_subvolumes["@"].path.replace(repo.mount_paths["@"] + "/"," "))){
4322 subvol = sys_subvolumes["@"];
4323 }
4324 else if ((sys_subvolumes.size > 0)
4325 && sys_subvolumes.has_key("@home")
4326 && line.has_suffix(sys_subvolumes["@home"].path.replace(repo.mount_paths["@home"] + "/"," "))){
4327
4328 subvol = sys_subvolumes["@home"];
4329 }
4330 else {
4331 foreach(var bak in repo.snapshots){
4332 foreach(var sub in bak.subvolumes.values){
4333 if (line.has_suffix(sub.path.replace(repo.mount_paths[sub.name] + "/",""))){
4334 subvol = sub;
4335 break;
4336 }
4337 }
4338 }
4339 }
4340
4341 if (subvol != null){
4342 subvol.id = long.parse(parts[1]);
4343 }
4344 }
4345
4346 return true;
4347 }

References _, TeeJee.ProcessHelper.exec_sync(), TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), SnapshotRepo.mount_paths, repo, SnapshotRepo.snapshots, and sys_subvolumes.

Referenced by query_subvolume_ids().

◆ query_subvolume_ids()

bool Main.query_subvolume_ids ( )
inline

Definition at line 4280 of file Main.vala.

4280 {
4281 bool ok = query_subvolume_id("@");
4282 if ((repo.device_home != null) && (repo.device.uuid != repo.device_home.uuid)){
4283 ok = ok && query_subvolume_id("@home");
4284 }
4285 return ok;
4286 }
bool query_subvolume_id(string subvol_name)
Definition Main.vala:4288

References SnapshotRepo.device, SnapshotRepo.device_home, query_subvolume_id(), repo, and Device.uuid.

Referenced by query_subvolume_info_thread().

◆ query_subvolume_info()

void Main.query_subvolume_info ( SnapshotRepo parent_repo)
inline

Definition at line 4222 of file Main.vala.

4222 {
4223
4224 // SnapshotRepo constructor calls this code in load_snapshots()
4225 // save the new object reference to repo since repo still holds previous object
4226 repo = parent_repo;
4227
4228 // TODO: move query_subvolume_info() and related methods to SnapshotRepo
4229
4230 if ((repo == null) || !repo.btrfs_mode){
4231 return;
4232 }
4233
4234 log_debug(_("Querying subvolume info..."));
4235
4236 try {
4239 new Thread<void>.try ("query-subvolume-info", () => {query_subvolume_info_thread();});
4240 } catch (Error e) {
4243 log_error (e.message);
4244 }
4245
4247 gtk_do_events ();
4248 Thread.usleep((ulong) GLib.TimeSpan.MILLISECOND * 100);
4249 }
4250
4251 log_debug(_("Query completed"));
4252 }
void query_subvolume_info_thread()
Definition Main.vala:4254
bool thread_subvol_info_success
Definition Main.vala:112
bool thread_subvol_info_running
Definition Main.vala:111

References _, SnapshotRepo.btrfs_mode, Error, TeeJee.GtkHelper.gtk_do_events(), TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), query_subvolume_info_thread(), repo, thread_subvol_info_running, and thread_subvol_info_success.

Referenced by SnapshotRepo.load_snapshots().

◆ query_subvolume_info_thread()

void Main.query_subvolume_info_thread ( )
inline

Definition at line 4254 of file Main.vala.

4254 {
4255
4257
4258 //query IDs
4259 bool ok = query_subvolume_ids();
4260
4261 if (!ok){
4264 return;
4265 }
4266
4268 bool success = query_subvolume_quotas();
4269
4272 }
4273 }
4274
4277 return;
4278 }
bool query_subvolume_ids()
Definition Main.vala:4280
QGroupStatus _btrfs_qgroups_enabled_internal
Definition Main.vala:180
QGroupStatus
Definition Main.vala:174
bool query_subvolume_quotas()
Definition Main.vala:4349

References _btrfs_qgroups_enabled_internal, ENABLED, query_subvolume_ids(), query_subvolume_quotas(), thread_subvol_info_running, and thread_subvol_info_success.

Referenced by query_subvolume_info().

◆ query_subvolume_quota()

bool Main.query_subvolume_quota ( string subvol_name)
inline

Definition at line 4357 of file Main.vala.

4357 {
4358 log_debug("query_subvolume_quota():%s".printf(subvol_name));
4359
4360 string cmd = "";
4361 string std_out;
4362 string std_err;
4363 int ret_val;
4364
4365 string options = use_option_raw ? "--raw" : "";
4366
4367 cmd = "btrfs qgroup show %s '%s'".printf(options, repo.mount_paths[subvol_name]);
4368 log_debug(cmd);
4369 ret_val = exec_sync(cmd, out std_out, out std_err);
4370
4371 if (ret_val != 0){
4372 if (use_option_raw){
4373 use_option_raw = false;
4374
4375 // try again without --raw option
4376 cmd = "btrfs qgroup show '%s'".printf(repo.mount_paths[subvol_name]);
4377 log_debug(cmd);
4378 ret_val = exec_sync(cmd, out std_out, out std_err);
4379 }
4380
4381 if (ret_val != 0){
4382 if (std_err.contains("not enabled")) {
4383 log_msg("btrfs: Quotas are not enabled");
4384 return false;
4385 }
4386 log_error (std_err);
4387 log_error(_("btrfs returned an error") + ": %d".printf(ret_val));
4388 log_error(_("Failed to query subvolume quota"));
4389 return false;
4390 }
4391 }
4392
4393 /* Sample Output:
4394 *
4395 qgroupid rfer excl
4396 -------- ---- ----
4397 0/5 106496 106496
4398 0/257 3825262592 557056
4399 0/258 12689408 49152
4400 * */
4401
4402 foreach(string line in std_out.split("\n")){
4403 if (line == null) { continue; }
4404
4405 string[] parts = line.split(" ");
4406 if (parts.length < 3) { continue; }
4407 if (parts[0].split("/").length < 2) { continue; }
4408
4409 int subvol_id = int.parse(parts[0].split("/")[1]);
4410
4411 Subvolume subvol = null;
4412
4413 if ((sys_subvolumes.size > 0) && (sys_subvolumes["@"].id == subvol_id)){
4414
4415 subvol = sys_subvolumes["@"];
4416 }
4417 else if ((sys_subvolumes.size > 0)
4418 && sys_subvolumes.has_key("@home")
4419 && (sys_subvolumes["@home"].id == subvol_id)){
4420
4421 subvol = sys_subvolumes["@home"];
4422 }
4423 else {
4424 foreach(var bak in repo.snapshots){
4425 foreach(var sub in bak.subvolumes.values){
4426 if (sub.id == subvol_id){
4427 subvol = sub;
4428 }
4429 }
4430 }
4431 }
4432
4433 if (subvol != null){
4434 int part_num = -1;
4435 foreach(string part in parts){
4436 if (part.strip().length > 0){
4437 part_num ++;
4438 switch (part_num){
4439 case 1:
4440 subvol.total_bytes = int64.parse(part);
4441 break;
4442 case 2:
4443 subvol.unshared_bytes = int64.parse(part);
4444 break;
4445 default:
4446 //ignore
4447 break;
4448 }
4449 }
4450 }
4451 }
4452 }
4453
4454 foreach(var bak in repo.snapshots){
4455 bak.update_control_file();
4456 }
4457
4458 return true;
4459 }
bool use_option_raw
Definition Main.vala:142

References _, TeeJee.ProcessHelper.exec_sync(), TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), TeeJee.Logging.log_msg(), SnapshotRepo.mount_paths, repo, SnapshotRepo.snapshots, sys_subvolumes, and use_option_raw.

Referenced by query_subvolume_quotas().

◆ query_subvolume_quotas()

bool Main.query_subvolume_quotas ( )
inline

Definition at line 4349 of file Main.vala.

4349 {
4350 bool ok = query_subvolume_quota("@");
4352 ok = ok && query_subvolume_quota("@home");
4353 }
4354 return ok;
4355 }
bool query_subvolume_quota(string subvol_name)
Definition Main.vala:4357

References SnapshotRepo.device, SnapshotRepo.device_home, query_subvolume_quota(), repo, and Device.uuid.

Referenced by query_subvolume_info_thread().

◆ restore_current_console()

bool Main.restore_current_console ( string sh_sync,
string sh_finish )
inlineprivate

Definition at line 2722 of file Main.vala.

2722 {
2723
2724 log_debug("Main: restore_current_console()");
2725
2726 string script = sh_sync + sh_finish;
2727 int ret_val = -1;
2728
2729 if (cmd_verbose){
2730 //current/other system, console, verbose
2731 ret_val = exec_script_sync(script, null, null, false, false, false, true);
2732 log_msg("");
2733 }
2734 else{
2735 //current/other system, console, quiet
2736 string std_out, std_err;
2737 ret_val = exec_script_sync(script, out std_out, out std_err);
2738 log_to_file(std_out);
2739 log_to_file(std_err);
2740 }
2741
2742 return (ret_val == 0);
2743 }
bool cmd_verbose
Definition Main.vala:150
void log_to_file(string message, bool highlight=false)

References cmd_verbose, TeeJee.ProcessHelper.exec_script_sync(), TeeJee.Logging.log_debug(), TeeJee.Logging.log_msg(), and TeeJee.Logging.log_to_file().

Referenced by restore_execute_rsync().

◆ restore_current_gui()

bool Main.restore_current_gui ( string sh_sync,
string sh_finish )
inlineprivate

Definition at line 2745 of file Main.vala.

2745 {
2746
2747 log_debug("Main: restore_current_gui()");
2748
2749 string script = sh_sync + sh_finish;
2750 string temp_script = save_bash_script_temp(script);
2751
2752 var dlg = new TerminalWindow.with_parent(parent_window);
2753 dlg.execute_script(temp_script, true);
2754
2755 return true;
2756 }
string? save_bash_script_temp(string commands, string? script_path=null, bool force_locale=true, bool supress_errors=false)

References TerminalWindow.execute_script(), TeeJee.Logging.log_debug(), parent_window, TeeJee.ProcessHelper.save_bash_script_temp(), and TerminalWindow.with_parent().

Referenced by restore_execute_rsync().

◆ restore_execute_btrfs()

bool Main.restore_execute_btrfs ( )
inline

Definition at line 3150 of file Main.vala.

3150 {
3151
3152 log_debug("Main: restore_execute_btrfs()");
3153
3155
3156 log_msg(string.nfill(78, '-'));
3157
3158 if (!ok){
3159 thread_restore_running = false;
3160 thr_success = false;
3161 return thr_success;
3162 }
3163
3164 // restore snapshot subvolumes by creating new subvolume snapshots
3165
3166 foreach(var subvol in snapshot_to_restore.subvolumes.values){
3167
3168 if ((subvol.name == "@home") && !include_btrfs_home_for_restore){ continue; }
3169
3170 subvol.restore();
3171 }
3172
3173 log_msg(_("Restore completed"));
3174 thr_success = true;
3175
3176 // Perform any post-restore actions
3177 log_debug("Running post-restore tasks...");
3178
3179 string sh = "test -d \"/etc/bastionguard-backup/restore-hooks.d\" &&" +
3180 " export TS_SNAPSHOT_PATH=\"" + snapshot_to_restore.path + "\" &&" +
3181 " run-parts --verbose /etc/bastionguard-backup/restore-hooks.d";
3182
3183 exec_script_sync(sh, null, null, false, false, false, true);
3184
3185 log_debug("Finished running post-restore tasks...");
3186
3188 log_msg(_("Snapshot will become active after system is rebooted."));
3189 }
3190
3191 log_msg(string.nfill(78, '-'));
3192
3193 thread_restore_running = false;
3194 return thr_success;
3195 }
bool thread_restore_running
Definition Main.vala:105
bool thr_success
Definition Main.vala:103
bool create_pre_restore_snapshot_btrfs()
Definition Main.vala:3197

References _, create_pre_restore_snapshot_btrfs(), TeeJee.ProcessHelper.exec_script_sync(), include_btrfs_home_for_restore, TeeJee.Logging.log_debug(), TeeJee.Logging.log_msg(), restore_current_system, snapshot_to_restore, Snapshot.subvolumes, thr_success, and thread_restore_running.

Referenced by restore_snapshot().

◆ restore_execute_rsync()

bool Main.restore_execute_rsync ( )
inline

Definition at line 3065 of file Main.vala.

3065 {
3066
3067 log_debug("Main: restore_execute_rsync()");
3068
3069 try{
3070 log_debug("source_path=%s".printf(restore_source_path));
3071 log_debug("target_path=%s".printf(restore_target_path));
3072
3073 string sh_sync, sh_finish;
3074 create_restore_scripts(out sh_sync, out sh_finish);
3075
3077
3079 file_delete(restore_log_file + "-changes");
3081
3083 string control_file_path = path_combine(snapshot_to_restore.path,".sync-restore");
3084
3085 var f = File.new_for_path(control_file_path);
3086 if(f.query_exists()){
3087 f.delete(); //delete existing file
3088 }
3089
3090 file_write(control_file_path, snapshot_to_restore.path); //save snapshot name
3091 }
3092
3093 // run the scripts --------------------
3094
3095 if (snapshot_to_restore != null){
3096 if (dry_run){
3097 log_msg(_("Comparing Files (Dry Run)..."));
3098 }
3099 else{
3100 log_msg(_("Restoring snapshot..."));
3101 }
3102 }
3103 else{
3104 log_msg(_("Cloning system..."));
3105 }
3106
3107 progress_text = _("Syncing files with rsync...");
3109
3110 bool ok = true;
3111
3112 if (app_mode == ""){ // GUI
3114 ok = restore_other_gui(sh_sync, sh_finish);
3115 }
3116 else{
3117 ok = restore_current_gui(sh_sync, sh_finish);
3118 }
3119 }
3120 else{
3122 ok = restore_current_console(sh_sync, sh_finish);
3123 }
3124 else{
3125 ok = restore_other_console(sh_sync, sh_finish);
3126 }
3127 }
3128
3129 if (!dry_run){
3130
3131 log_msg(_("Restore completed"));
3132 thr_success = true;
3133
3134 log_msg(string.nfill(78, '-'));
3135
3136 unmount_target_device(false);
3137
3139 }
3140 }
3141 catch(Error e){
3142 log_error (e.message);
3143 thr_success = false;
3144 }
3145
3146 thread_restore_running = false;
3147 return thr_success;
3148 }
bool restore_other_console(string sh_sync, string sh_finish)
Definition Main.vala:2758
bool restore_current_gui(string sh_sync, string sh_finish)
Definition Main.vala:2745
bool restore_other_gui(string sh_sync, string sh_finish)
Definition Main.vala:2809
bool restore_current_console(string sh_sync, string sh_finish)
Definition Main.vala:2722
void check_and_repair_filesystems()
Definition Main.vala:3051
bool save_exclude_list_for_restore(string output_path)
Definition Main.vala:1004
void create_restore_scripts(out string sh_sync, out string sh_finish)
Definition Main.vala:2537
bool file_write(string file_path, string contents)

References _, app_mode, check_and_repair_filesystems(), create_restore_scripts(), dry_run, Error, TeeJee.FileSystem.file_delete(), TeeJee.FileSystem.file_write(), TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), TeeJee.Logging.log_msg(), Snapshot.path, TeeJee.FileSystem.path_combine(), progress_text, restore_current_console(), restore_current_gui(), restore_current_system, restore_log_file, restore_other_console(), restore_other_gui(), restore_source_path, restore_target_path, save_exclude_list_for_restore(), snapshot_to_restore, thr_success, thread_restore_running, and unmount_target_device().

Referenced by restore_snapshot().

◆ restore_other_console()

bool Main.restore_other_console ( string sh_sync,
string sh_finish )
inlineprivate

Definition at line 2758 of file Main.vala.

2758 {
2759
2760 log_debug("Main: restore_other_console()");
2761
2762 // execute sh_sync --------------------
2763
2764 string script = sh_sync;
2765 int ret_val = -1;
2766
2767 if (cmd_verbose){
2768 ret_val = exec_script_sync(script, null, null, false, false, false, true);
2769 log_msg("");
2770 }
2771 else{
2772 string std_out, std_err;
2773 ret_val = exec_script_sync(script, out std_out, out std_err);
2774 log_to_file(std_out);
2775 log_to_file(std_err);
2776 }
2777
2778 // update files -------------------
2779
2782
2783 progress_text = _("Parsing log file...");
2785 var task = new RsyncTask();
2786 task.parse_log(restore_log_file);
2787
2788 // execute sh_finish --------------------
2789
2790 log_debug("executing sh_finish: ");
2791 log_debug(sh_finish);
2792
2793 script = sh_finish;
2794
2795 if (cmd_verbose){
2796 ret_val = exec_script_sync(script, null, null, false, false, false, true);
2797 log_msg("");
2798 }
2799 else{
2800 string std_out, std_err;
2801 ret_val = exec_script_sync(script, out std_out, out std_err);
2802 log_to_file(std_out);
2803 log_to_file(std_err);
2804 }
2805
2806 return (ret_val == 0);
2807 }
void fix_fstab_file(string target_path)
Definition Main.vala:2895
void fix_crypttab_file(string target_path)
Definition Main.vala:2988

References _, cmd_verbose, TeeJee.ProcessHelper.exec_script_sync(), fix_crypttab_file(), fix_fstab_file(), TeeJee.Logging.log_debug(), TeeJee.Logging.log_msg(), TeeJee.Logging.log_to_file(), progress_text, restore_log_file, restore_target_path, RsyncTask.RsyncTask(), and task.

Referenced by restore_execute_rsync().

◆ restore_other_gui()

bool Main.restore_other_gui ( string sh_sync,
string sh_finish )
inlineprivate

Definition at line 2809 of file Main.vala.

2809 {
2810
2811 log_debug("Main: restore_other_gui()");
2812
2813 progress_text = _("Building file list...");
2814
2815 task = new RsyncTask();
2816 task.relative = false;
2817 task.verbose = true;
2818 task.delete_extra = true;
2819 task.delete_excluded = false;
2820 task.delete_after = true;
2821
2822 task.dry_run = dry_run;
2823
2824 if (mirror_system){
2825 task.source_path = "/";
2826 }
2827 else{
2828 task.source_path = path_combine(snapshot_to_restore.path, "localhost");
2829 }
2830
2831 task.dest_path = restore_target_path;
2832
2833 task.exclude_from_file = restore_exclude_file;
2834
2835 task.rsync_log_file = restore_log_file;
2836
2837 if ((snapshot_to_restore != null) && (snapshot_to_restore.file_count > 0)){
2838 task.prg_count_total = snapshot_to_restore.file_count;
2839 }
2840 else if (Main.first_snapshot_count > 0){
2841 task.prg_count_total = Main.first_snapshot_count;
2842 }
2843 else{
2844 task.prg_count_total = 500000;
2845 }
2846
2847 task.execute();
2848
2849 while (task.status == AppStatus.RUNNING){
2850 sleep(1000);
2851
2852 if (task.status_line.length > 0){
2853
2854 if (dry_run){
2855 progress_text = _("Comparing files with rsync...");
2856 }
2857 else{
2858 progress_text = _("Syncing files with rsync...");
2859 }
2860 }
2861
2862 gtk_do_events();
2863 }
2864
2865 if (dry_run){
2866 return true; // no need to continue
2867 }
2868
2869 // update files after sync --------------------
2870
2873
2874 progress_text = _("Parsing log file...");
2876 var task = new RsyncTask();
2877 task.parse_log(restore_log_file);
2878
2879 // execute sh_finish ------------
2880
2882 progress_text = _("Updating bootloader configuration...");
2883 }
2884
2885 log_debug("executing sh_finish: ");
2886 log_debug(sh_finish);
2887
2888 int ret_val = exec_script_sync(sh_finish, null, null, false, false, false, true);
2889
2890 log_debug("script exit code: %d".printf(ret_val));
2891
2892 return (ret_val == 0);
2893 }
string status_line
int64 file_count
Definition Snapshot.vala:43

References _, dry_run, TeeJee.ProcessHelper.exec_script_sync(), AsyncTask.execute(), Snapshot.file_count, fix_crypttab_file(), fix_fstab_file(), TeeJee.GtkHelper.gtk_do_events(), TeeJee.Logging.log_debug(), TeeJee.Logging.log_msg(), Main(), mirror_system, Snapshot.path, TeeJee.FileSystem.path_combine(), progress_text, reinstall_grub2, restore_exclude_file, restore_log_file, restore_target_path, RsyncTask.RsyncTask(), TeeJee.System.sleep(), snapshot_to_restore, AsyncTask.status, AsyncTask.status_line, task, update_grub, and update_initramfs.

Referenced by restore_execute_rsync().

◆ restore_snapshot()

bool Main.restore_snapshot ( Gtk.Window? parent_win)
inline

Definition at line 2298 of file Main.vala.

2298 {
2299
2300 log_debug("Main: restore_snapshot()");
2301
2302 parent_window = parent_win;
2303
2304 // remove mount points which will remain on root fs
2305
2306 for(int i = mount_list.size-1; i >= 0; i--){
2307 var entry = mount_list[i];
2308 if (entry.device == null){
2309 mount_list.remove(entry);
2310 }
2311 }
2312
2313 // check if we have all required inputs and abort on error
2314
2315 if (!mirror_system){
2316
2317 if (repo.device == null){
2318 log_error(_("Backup device not specified!"));
2319 return false;
2320 }
2321 else{
2322 log_msg(string.nfill(78, '*'));
2323 log_msg(_("Backup Device") + ": %s".printf(repo.device.device));
2324 log_msg(string.nfill(78, '*'));
2325 }
2326
2327 if (snapshot_to_restore == null){
2328 log_error(_("Snapshot to restore not specified!"));
2329 return false;
2330 }
2332 log_error(_("Invalid Snapshot"));
2333 log_error(_("Selected snapshot is marked for deletion"));
2334 return false;
2335 }
2336 else {
2337 log_msg(string.nfill(78, '*'));
2338 log_msg("%s: %s ~ %s".printf(_("Snapshot"), snapshot_to_restore.name, snapshot_to_restore.description));
2339 log_msg(string.nfill(78, '*'));
2340 }
2341 }
2342
2343 // final check - check if target root device is mounted
2344
2345 if (btrfs_mode){
2346 if (repo.mount_paths["@"].length == 0){
2347 log_error(_("BTRFS device is not mounted") + ": @");
2348 return false;
2349 }
2350 if (include_btrfs_home_for_restore && (repo.mount_paths["@home"].length == 0)){
2351 log_error(_("BTRFS device is not mounted") + ": @home");
2352 return false;
2353 }
2354 }
2355 else{
2356 if (dst_root == null){
2357 log_error(_("Target device not specified!"));
2358 return false;
2359 }
2360
2362 if (mount_point_restore.strip().length == 0){
2363 log_error(_("Target device is not mounted"));
2364 return false;
2365 }
2366 }
2367 }
2368
2369 try {
2371 thr_success = false;
2372
2373 if (btrfs_mode){
2374 new Thread<bool>.try ("restore-execute-btrfs", () => {restore_execute_btrfs(); return true;});
2375 }
2376 else{
2377 new Thread<bool>.try ("restore-execute-rsync", () => {restore_execute_rsync(); return true;});
2378 }
2379 }
2380 catch (Error e) {
2381 thread_restore_running = false;
2382 thr_success = false;
2383 log_error (e.message);
2384 }
2385
2386 while (thread_restore_running){
2387 gtk_do_events ();
2388 Thread.usleep((ulong) GLib.TimeSpan.MILLISECOND * 100);
2389 }
2390
2391 if (!dry_run){
2392 snapshot_to_restore = null;
2393 }
2394
2395 log_debug("Main: restore_snapshot(): exit");
2396
2397 return thr_success;
2398 }
bool restore_execute_btrfs()
Definition Main.vala:3150
bool restore_execute_rsync()
Definition Main.vala:3065
string description
Definition Snapshot.vala:42
bool marked_for_deletion
Definition Snapshot.vala:51

References _, btrfs_mode, Snapshot.description, Device.device, SnapshotRepo.device, dry_run, dst_root, Error, TeeJee.GtkHelper.gtk_do_events(), include_btrfs_home_for_restore, TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), TeeJee.Logging.log_msg(), Snapshot.marked_for_deletion, mirror_system, mount_list, SnapshotRepo.mount_paths, mount_point_restore, Snapshot.name, parent_window, repo, restore_current_system, restore_execute_btrfs(), restore_execute_rsync(), snapshot_to_restore, thr_success, and thread_restore_running.

Referenced by AppConsole.restore_snapshot(), and RestoreBox.restore_thread().

◆ run_post_backup_hooks()

void Main.run_post_backup_hooks ( string snapshot_path)
inlineprivate

Definition at line 1811 of file Main.vala.

1811 {
1812 const string backuphooksdir = "/etc/bastionguard-backup/backup-hooks.d";
1813 FileType fileType = File.new_for_path(backuphooksdir).query_file_type(FileQueryInfoFlags.NONE);
1814 if(fileType == FileType.DIRECTORY) {
1815 log_debug("Running post-backup tasks...");
1816
1817 string sh = "export TS_SNAPSHOT_PATH=\"" + snapshot_path + "\" &&" +
1818 " run-parts --verbose \"%s\"".printf(backuphooksdir);
1819 exec_script_sync(sh, null, null, false, false, false, true);
1820
1821 log_debug("Finished running post-backup tasks...");
1822 } else {
1823 log_debug("Backup hooks skipped, because %s does not exist".printf(backuphooksdir));
1824 }
1825 }

References TeeJee.ProcessHelper.exec_script_sync(), and TeeJee.Logging.log_debug().

Referenced by create_snapshot_with_btrfs(), and create_snapshot_with_rsync().

◆ save_app_config()

void Main.save_app_config ( )
inline

Definition at line 3338 of file Main.vala.

3338 {
3339
3340 log_debug("Main: save_app_config()");
3341
3342 var config = new Json.Object();
3343
3344 if ((repo != null) && repo.available()){
3345 config.set_string_member("backup_device_uuid",
3346 (repo.device == null) ? "" : repo.device.uuid);
3347
3348 config.set_string_member("parent_device_uuid",
3350 }
3351 else{
3352 config.set_string_member("backup_device_uuid", backup_uuid);
3353 config.set_string_member("parent_device_uuid", backup_parent_uuid);
3354 }
3355
3356 config.set_string_member("do_first_run", false.to_string());
3357 config.set_string_member("btrfs_mode", btrfs_mode.to_string());
3358 config.set_string_member("include_btrfs_home_for_backup", include_btrfs_home_for_backup.to_string());
3359 config.set_string_member("include_btrfs_home_for_restore", include_btrfs_home_for_restore.to_string());
3360 config.set_string_member("stop_cron_emails", stop_cron_emails.to_string());
3361
3362 config.set_string_member("schedule_monthly", schedule_monthly.to_string());
3363 config.set_string_member("schedule_weekly", schedule_weekly.to_string());
3364 config.set_string_member("schedule_daily", schedule_daily.to_string());
3365 config.set_string_member("schedule_hourly", schedule_hourly.to_string());
3366 config.set_string_member("schedule_boot", schedule_boot.to_string());
3367
3368 config.set_string_member("count_monthly", count_monthly.to_string());
3369 config.set_string_member("count_weekly", count_weekly.to_string());
3370 config.set_string_member("count_daily", count_daily.to_string());
3371 config.set_string_member("count_hourly", count_hourly.to_string());
3372 config.set_string_member("count_boot", count_boot.to_string());
3373
3374 if (repo.available() && repo.has_snapshots()) {
3375 config.set_string_member("snapshot_size", first_snapshot_size.to_string());
3376 config.set_string_member("snapshot_count", first_snapshot_count.to_string());
3377 }
3378 else {
3381 }
3382
3383 config.set_string_member("date_format", date_format);
3384
3385 Json.Array arr = new Json.Array();
3386 foreach(string path in exclude_list_user){
3387 arr.add_string_element(path);
3388 }
3389 config.set_array_member("exclude", arr);
3390
3391 arr = new Json.Array();
3392 foreach(var name in exclude_app_names){
3393 arr.add_string_element(name);
3394 }
3395 config.set_array_member("exclude-apps", arr);
3396
3397 var json = new Json.Generator();
3398 json.pretty = true;
3399 json.indent = 2;
3400 var node = new Json.Node(NodeType.OBJECT);
3401 node.set_object(config);
3402 json.set_root(node);
3403
3404 try{
3405 string conf_dir = File.new_for_path(this.app_conf_path).get_parent().get_path();
3406
3407 if (!FileUtils.test(conf_dir, FileTest.IS_DIR)) {
3408 DirUtils.create_with_parents(conf_dir, 0755);
3409 log_debug("Directory configurazione creata: " + conf_dir);
3410 }
3411
3412 json.to_file(this.app_conf_path);
3413 } catch (Error e) {
3414 log_error(e.message);
3415 }
3416
3417 if ((app_mode == "") || (LOG_DEBUG)){
3418 log_msg(_("App config saved") + ": %s".printf(this.app_conf_path));
3419 }
3420 }
nlohmann::json json
Definition Backend.cpp:2908
Device parent
Definition Device.vala:86
bool has_parent()
Definition Device.vala:243
static int64 first_snapshot_count
Definition Main.vala:124

References _, app_mode, SnapshotRepo.available(), backup_parent_uuid, backup_uuid, btrfs_mode, count_boot, count_daily, count_hourly, count_monthly, count_weekly, date_format, SnapshotRepo.device, Error, exclude_app_names, exclude_list_user, first_snapshot_count, first_snapshot_size, Device.has_parent(), SnapshotRepo.has_snapshots(), include_btrfs_home_for_backup, include_btrfs_home_for_restore, TeeJee.Logging.LOG_DEBUG, TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), TeeJee.Logging.log_msg(), Device.parent, repo, schedule_boot, schedule_daily, schedule_hourly, schedule_monthly, schedule_weekly, stop_cron_emails, and Device.uuid.

Referenced by estimate_system_size(), exit_app(), import_timeshift_config_if_available(), and MainWindow.settings_changed().

◆ save_exclude_list_for_backup()

string? Main.save_exclude_list_for_backup ( string output_path)
inlineprivate

Definition at line 984 of file Main.vala.

984 {
985
986 log_debug("Main: save_exclude_list_for_backup()");
987
989
990 var txt = "";
991 foreach(var pattern in list){
992 if (pattern.strip().length > 0){
993 txt += "%s\n".printf(pattern);
994 }
995 }
996
997 string list_file = path_combine(output_path, "exclude.list");
998 if (file_write(list_file, txt)) {
999 return list_file;
1000 }
1001 return null;
1002 }
Gee.ArrayList< string > create_exclude_list_for_backup()
Definition Main.vala:797

References create_exclude_list_for_backup(), TeeJee.FileSystem.file_write(), TeeJee.Logging.log_debug(), and TeeJee.FileSystem.path_combine().

Referenced by create_snapshot_with_rsync(), estimate_system_size(), and get_space_needed_for_rsync_snapshot().

◆ save_exclude_list_for_restore()

bool Main.save_exclude_list_for_restore ( string output_path)
inline

Definition at line 1004 of file Main.vala.

1004 {
1005
1006 log_debug("Main: save_exclude_list_for_restore()");
1007
1009
1010 log_debug("Exclude list -------------");
1011
1012 var txt = "";
1013 foreach(var pattern in list){
1014 if (pattern.strip().length > 0){
1015 txt += "%s\n".printf(pattern);
1016 log_debug(pattern);
1017 }
1018 }
1019
1020 return file_write(restore_exclude_file, txt);
1021 }
Gee.ArrayList< string > create_exclude_list_for_restore()
Definition Main.vala:907

References create_exclude_list_for_restore(), TeeJee.FileSystem.file_write(), TeeJee.Logging.log_debug(), and restore_exclude_file.

Referenced by restore_execute_rsync().

◆ save_exclude_list_selections()

void Main.save_exclude_list_selections ( )
inline

Definition at line 1023 of file Main.vala.

1023 {
1024
1025 log_debug("Main: save_exclude_list_selections()");
1026
1027 // add new selected items
1028 foreach(var entry in exclude_list_apps){
1029 if (entry.enabled && !exclude_app_names.contains(entry.name)){
1030 exclude_app_names.add(entry.name);
1031 log_debug("add app name: %s".printf(entry.name));
1032 }
1033 }
1034
1035 // remove item only if present in current list and un-selected
1036 foreach(var entry in exclude_list_apps){
1037 if (!entry.enabled && exclude_app_names.contains(entry.name)){
1038 exclude_app_names.remove(entry.name);
1039 log_debug("remove app name: %s".printf(entry.name));
1040 }
1041 }
1042
1043 exclude_app_names.sort((a,b) => {
1044 return Posix.strcmp(a,b);
1045 });
1046 }

References exclude_app_names, exclude_list_apps, and TeeJee.Logging.log_debug().

Referenced by RestoreWindow.validate_current_tab().

◆ set_first_run_flag()

void Main.set_first_run_flag ( )
inline

Definition at line 3708 of file Main.vala.

3708 {
3709
3710 first_run = true;
3711
3712 log_msg("First run mode (config file not found)");
3713
3714 // load some defaults for first-run based on user's system type
3715
3716 bool supported = sys_subvolumes.has_key("@") && cmd_exists("btrfs"); // && sys_subvolumes.has_key("@home")
3717 if (supported || (cmd_btrfs_mode == true)){
3718 log_msg(_("Selected default snapshot type") + ": %s".printf("BTRFS"));
3719 btrfs_mode = true;
3720 }
3721 else{
3722 log_msg(_("Selected default snapshot type") + ": %s".printf("RSYNC"));
3723 btrfs_mode = false;
3724 }
3725 }

References _, btrfs_mode, cmd_btrfs_mode, first_run, TeeJee.Logging.log_msg(), and sys_subvolumes.

Referenced by load_app_config().

◆ set_tags()

void Main.set_tags ( Snapshot snapshot)
inlineprivate

Definition at line 1827 of file Main.vala.

1827 {
1828
1829 // add tags passed on commandline for both --check and --create
1830
1831 foreach(string tag in cmd_tags.split(",")){
1832 switch(tag.strip().up()){
1833 case "O":
1834 snapshot.add_tag("ondemand");
1835 break;
1836 case "B":
1837 snapshot.add_tag("boot");
1838 break;
1839 case "H":
1840 snapshot.add_tag("hourly");
1841 break;
1842 case "D":
1843 snapshot.add_tag("daily");
1844 break;
1845 case "W":
1846 snapshot.add_tag("weekly");
1847 break;
1848 case "M":
1849 snapshot.add_tag("monthly");
1850 break;
1851 }
1852 }
1853
1854 // add tag as ondemand if no other tag is specified
1855
1856 if (snapshot.tags.size == 0){
1857 snapshot.add_tag("ondemand");
1858 }
1859 }
string cmd_tags
Definition Main.vala:153
Gee.ArrayList< string > tags
Definition Snapshot.vala:44

References cmd_tags.

Referenced by create_snapshot_with_btrfs(), and create_snapshot_with_rsync().

◆ setup_env()

void Main.setup_env ( )
inlinestatic

Definition at line 366 of file Main.vala.

366 {
367 Pid user_pid = TeeJee.ProcessHelper.get_user_process();
368 string[]? user_env = TeeJee.ProcessHelper.get_process_env(user_pid);
369 if(user_env == null) {
370 return;
371 }
372
373 // copy all required enviroment vars from the user to this process
374 string[] targets = {"GTK_THEME", "DISPLAY", "XAUTHORITY", "DBUS_SESSION_BUS_ADDRESS"};
375 foreach (string target in targets) {
376 string user_var = TeeJee.ProcessHelper.get_env(user_env, target);
377 if(user_var != null) {
378 GLib.Environment.set_variable(target, user_var, true);
379 }
380 }
381
382 string xdg_runtime_dir = TeeJee.ProcessHelper.get_env(user_env, "XDG_RUNTIME_DIR");
383 string wayland_display = TeeJee.ProcessHelper.get_env(user_env, "WAYLAND_DISPLAY");
384
385 if (wayland_display != null && xdg_runtime_dir != null) {
386 string path = "%s/%s".printf(xdg_runtime_dir, wayland_display);
387 GLib.Environment.set_variable("WAYLAND_DISPLAY", path, true);
388 GLib.Environment.set_variable("XDG_RUNTIME_DIR", "/run/user/0", true);
389 }
390 }

Referenced by AppConsole.main(), and AppGtk.main().

◆ try_select_default_device_for_backup()

void Main.try_select_default_device_for_backup ( Gtk.Window? parent_win)
inline

Definition at line 4110 of file Main.vala.

4110 {
4111
4112 log_debug("try_select_default_device_for_backup()");
4113
4114 // check if currently selected device can be used
4115 if (repo.available()){
4116 if (check_device_for_backup(repo.device, false)){
4117 if (repo.btrfs_mode != btrfs_mode){
4118 // reinitialize
4119 repo = new SnapshotRepo.from_device(repo.device, parent_win, btrfs_mode);
4120 }
4121 return;
4122 }
4123 else{
4124 repo = new SnapshotRepo.from_null();
4125 }
4126 }
4127
4129
4130 // In BTRFS mode, select the system disk if system disk is BTRFS
4131 if (btrfs_mode && sys_subvolumes.has_key("@")){
4132 var subvol_root = sys_subvolumes["@"];
4133 repo = new SnapshotRepo.from_device(subvol_root.get_device(), parent_win, btrfs_mode);
4134 return;
4135 }
4136
4137 foreach(var dev in partitions){
4138 if (check_device_for_backup(dev, false)){
4139 repo = new SnapshotRepo.from_device(dev, parent_win, btrfs_mode);
4140 break;
4141 }
4142 else{
4143 continue;
4144 }
4145 }
4146 }
bool check_device_for_backup(Device dev, bool unlock)
Definition Main.vala:4148
SnapshotRepo. from_null()

References SnapshotRepo.available(), btrfs_mode, SnapshotRepo.btrfs_mode, check_device_for_backup(), SnapshotRepo.device, SnapshotRepo.from_device(), SnapshotRepo.from_null(), TeeJee.Logging.log_debug(), partitions, repo, sys_subvolumes, and update_partitions().

Referenced by SnapshotBackendBox.init_backend(), and initialize_repo().

◆ unmount_device()

bool Main.unmount_device ( string mount_point,
bool exit_on_error = true )
inline

Definition at line 4034 of file Main.vala.

4034 {
4035 bool is_unmounted = Device.unmount(mount_point);
4036 if (!is_unmounted){
4037 if (exit_on_error){
4038 if (app_mode == ""){
4039 string title = _("Critical Error");
4040 string msg = _("Failed to unmount device!") + "\n" + _("Application will exit");
4041 gtk_messagebox(title, msg, null, true);
4042 }
4043 exit_app(1);
4044 }
4045 }
4046 return is_unmounted;
4047 }

References _, app_mode, exit_app(), and Device.unmount().

Referenced by unmount_target_device().

◆ unmount_target_device()

void Main.unmount_target_device ( bool exit_on_error = true)
inline

Definition at line 4019 of file Main.vala.

4019 {
4020
4021 if (mount_point_restore == null) { return; }
4022
4023 log_debug("unmount_target_device()");
4024
4025 //unmount the target device only if it was mounted by application
4026 if (mount_point_restore.has_prefix(mount_point_app)){ //always true
4027 unmount_device(mount_point_restore, exit_on_error);
4028 }
4029 else{
4030 //don't unmount
4031 }
4032 }
bool unmount_device(string mount_point, bool exit_on_error=true)
Definition Main.vala:4034

References TeeJee.Logging.log_debug(), mount_point_app, mount_point_restore, and unmount_device().

Referenced by exit_app(), mount_target_devices(), and restore_execute_rsync().

◆ update_partitions()

void Main.update_partitions ( )
inline

Definition at line 3819 of file Main.vala.

3819 {
3820
3821 log_debug("update_partitions()");
3822
3823 partitions.clear();
3824
3825 partitions = Device.get_filesystems();
3826
3827 foreach(var pi in partitions){
3828
3829 // sys_root and sys_home will be detected by detect_system_devices()
3830 if ((repo != null) && (repo.device != null) && (pi.uuid == repo.device.uuid)){
3831 repo.device = pi;
3832 }
3833 }
3834
3835 if (partitions.size == 0){
3836 log_error("ts: " + _("Failed to get partition list."));
3837 }
3838
3839 log_debug("partition list updated");
3840 }

References _, SnapshotRepo.device, Device.get_filesystems(), TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), partitions, repo, and Device.uuid.

Referenced by BackupDeviceBox.BackupDeviceBox(), BackupDeviceBox.change_backup_device(), BackupDeviceBox.device_list_refresh(), init_mount_list(), Main(), RestoreDeviceBox.refresh(), RestoreDeviceBox.RestoreDeviceBox(), and try_select_default_device_for_backup().

◆ validate_cmd_tags()

void Main.validate_cmd_tags ( )
inline

Definition at line 1861 of file Main.vala.

1861 {
1862 foreach(string tag in cmd_tags.split(",")){
1863 switch(tag.strip().up()){
1864 case "O":
1865 case "B":
1866 case "H":
1867 case "D":
1868 case "W":
1869 case "M":
1870 break;
1871 default:
1872 log_error(_("Unknown value specified for option --tags") + " (%s).".printf(tag));
1873 log_error(_("Expected values: O, B, H, D, W, M"));
1874 exit_app(1);
1875 break;
1876 }
1877 }
1878 }

References _, cmd_tags, exit_app(), and TeeJee.Logging.log_error().

Referenced by AppConsole.parse_arguments().

Member Data Documentation

◆ _btrfs_qgroups_enabled_internal

QGroupStatus Main._btrfs_qgroups_enabled_internal = QGroupStatus.UNKNOWN
private

Definition at line 180 of file Main.vala.

Referenced by query_subvolume_info_thread().

◆ _live_system

int Main._live_system = -1
private

Definition at line 169 of file Main.vala.

Referenced by live_system().

◆ app_conf_path

string Main.app_conf_path = ""

Definition at line 44 of file Main.vala.

Referenced by load_app_config().

◆ app_conf_path_default

string Main.app_conf_path_default = ""

Definition at line 46 of file Main.vala.

Referenced by load_app_config().

◆ app_conf_path_old

string Main.app_conf_path_old = ""

Definition at line 45 of file Main.vala.

Referenced by load_app_config().

◆ app_lock

AppLock Main.app_lock

Definition at line 128 of file Main.vala.

Referenced by exit_app(), and Main().

◆ app_mode

◆ app_path

string Main.app_path = ""

Definition at line 41 of file Main.vala.

Referenced by Main().

◆ backup_parent_uuid

string Main.backup_parent_uuid = ""

◆ backup_uuid

◆ btrfs_mode

◆ btrfs_version__can_recursive_delete

bool Main.btrfs_version__can_recursive_delete = false
static

Definition at line 55 of file Main.vala.

Referenced by check_btrfs_version_capabilities(), and Subvolume.remove().

◆ cmd_backup_device

string Main.cmd_backup_device = ""

Definition at line 147 of file Main.vala.

Referenced by initialize_repo().

◆ cmd_btrfs_mode

bool? Main.cmd_btrfs_mode = null

Definition at line 154 of file Main.vala.

Referenced by load_app_config(), parse_some_arguments(), and set_first_run_flag().

◆ cmd_comments

string Main.cmd_comments = ""

Definition at line 152 of file Main.vala.

Referenced by create_snapshot_with_btrfs(), and create_snapshot_with_rsync().

◆ cmd_confirm

bool Main.cmd_confirm = false

Definition at line 149 of file Main.vala.

Referenced by AppConsole.confirm_restore(), and AppConsole.select_grub_device().

◆ cmd_grub_device

string Main.cmd_grub_device = ""

Definition at line 145 of file Main.vala.

Referenced by AppConsole.select_grub_device().

◆ cmd_scripted

◆ cmd_skip_grub

bool Main.cmd_skip_grub = false

Definition at line 144 of file Main.vala.

Referenced by AppConsole.select_grub_device().

◆ cmd_snapshot

string Main.cmd_snapshot = ""

Definition at line 148 of file Main.vala.

Referenced by AppConsole.select_snapshot().

◆ cmd_tags

string Main.cmd_tags = ""

Definition at line 153 of file Main.vala.

Referenced by set_tags(), and validate_cmd_tags().

◆ cmd_target_device

string Main.cmd_target_device = ""

Definition at line 146 of file Main.vala.

Referenced by AppConsole.map_devices().

◆ cmd_verbose

bool Main.cmd_verbose = true

Definition at line 150 of file Main.vala.

Referenced by restore_current_console(), and restore_other_console().

◆ count_boot

◆ count_daily

◆ count_hourly

◆ count_monthly

◆ count_weekly

◆ current_distro

LinuxDistro Main.current_distro

Definition at line 84 of file Main.vala.

Referenced by create_snapshot_with_btrfs(), create_snapshot_with_rsync(), and Main().

◆ current_system_users

Gee.HashMap<string, SystemUser> Main.current_system_users

◆ date_format

string Main.date_format = "%Y-%m-%d %H:%M:%S"

◆ date_format_default

const string Main.date_format_default = "%Y-%m-%d %H:%M:%S"
static

◆ delete_file_task

◆ delete_list

◆ dry_run

◆ encrypted_home_dirs

string Main.encrypted_home_dirs = ""

Definition at line 166 of file Main.vala.

Referenced by detect_encrypted_dirs().

◆ encrypted_home_warning_shown

bool Main.encrypted_home_warning_shown = false

Definition at line 167 of file Main.vala.

◆ encrypted_private_dirs

string Main.encrypted_private_dirs = ""

Definition at line 171 of file Main.vala.

Referenced by detect_encrypted_dirs().

◆ encrypted_private_warning_shown

bool Main.encrypted_private_warning_shown = false

Definition at line 172 of file Main.vala.

◆ exclude_app_names

Gee.ArrayList<string> Main.exclude_app_names

◆ exclude_list_apps

◆ exclude_list_default

◆ exclude_list_default_extra

Gee.ArrayList<string> Main.exclude_list_default_extra

◆ exclude_list_home

◆ exclude_list_restore

Gee.ArrayList<string> Main.exclude_list_restore

Definition at line 65 of file Main.vala.

Referenced by add_default_exclude_entries(), and create_exclude_list_for_restore().

◆ exclude_list_user

◆ first_run

◆ first_snapshot_count

int64 Main.first_snapshot_count = 0
static

◆ first_snapshot_size

◆ grub_device

◆ include_btrfs_home_for_backup

◆ include_btrfs_home_for_restore

◆ log_dir

string Main.log_dir = ""

Definition at line 126 of file Main.vala.

Referenced by clean_logs(), and Main().

◆ log_file

string Main.log_file = ""

Definition at line 127 of file Main.vala.

Referenced by clean_logs(), create_snapshot_with_rsync(), and Main().

◆ MIN_FREE_SPACE

const uint64 Main.MIN_FREE_SPACE = 1 * GB
static

Definition at line 122 of file Main.vala.

Referenced by SnapshotRepo.has_space().

◆ mirror_system

◆ mount_list

◆ mount_point_app

string Main.mount_point_app = ""

◆ mount_point_restore

string Main.mount_point_restore = ""

Definition at line 81 of file Main.vala.

Referenced by mount_target_devices(), restore_snapshot(), and unmount_target_device().

◆ parent_window

Gtk.? Window Main.parent_window = null

◆ partitions

◆ progress_text

◆ reinstall_grub2

◆ repo

◆ retain_snapshots_max_days

int Main.retain_snapshots_max_days = 200

Definition at line 120 of file Main.vala.

◆ rsnapshot_conf_path

string Main.rsnapshot_conf_path = ""

Definition at line 43 of file Main.vala.

◆ schedule_boot

◆ schedule_daily

◆ schedule_hourly

◆ schedule_monthly

◆ schedule_weekly

◆ share_folder

string Main.share_folder = ""

Definition at line 42 of file Main.vala.

◆ snapshot_to_delete

Snapshot Main.snapshot_to_delete

◆ snapshot_to_restore

◆ space_check_task

RsyncSpaceCheckTask Main.space_check_task

Definition at line 162 of file Main.vala.

Referenced by get_space_needed_for_rsync_snapshot(), and BackupBox.take_snapshot().

◆ startup_delay_interval_mins

int Main.startup_delay_interval_mins = 10

Definition at line 119 of file Main.vala.

◆ stop_cron_emails

bool Main.stop_cron_emails = true

◆ sys_boot

Device Main.sys_boot

Definition at line 76 of file Main.vala.

Referenced by detect_system_devices().

◆ sys_efi

Device Main.sys_efi

Definition at line 77 of file Main.vala.

Referenced by detect_system_devices().

◆ sys_home

Device Main.sys_home

Definition at line 78 of file Main.vala.

Referenced by detect_system_devices().

◆ sys_root

◆ sys_subvolumes

◆ task

◆ thr_arg1

string Main.thr_arg1 = ""

Definition at line 115 of file Main.vala.

◆ thr_retval

int Main.thr_retval = -1

Definition at line 114 of file Main.vala.

◆ thr_success

bool Main.thr_success = false

Definition at line 103 of file Main.vala.

Referenced by restore_execute_btrfs(), restore_execute_rsync(), and restore_snapshot().

◆ thr_timeout_active

bool Main.thr_timeout_active = false

Definition at line 116 of file Main.vala.

◆ thr_timeout_cmd

string Main.thr_timeout_cmd = ""

Definition at line 117 of file Main.vala.

◆ thread_delete_running

◆ thread_delete_success

bool Main.thread_delete_success = false

Definition at line 109 of file Main.vala.

Referenced by delete_begin(), DeleteBox.delete_snapshots(), and delete_thread().

◆ thread_restore_running

bool Main.thread_restore_running = false

Definition at line 105 of file Main.vala.

Referenced by restore_execute_btrfs(), restore_execute_rsync(), and restore_snapshot().

◆ thread_restore_success

bool Main.thread_restore_success = false

Definition at line 106 of file Main.vala.

◆ thread_subvol_info_running

bool Main.thread_subvol_info_running = false

Definition at line 111 of file Main.vala.

Referenced by query_subvolume_info(), and query_subvolume_info_thread().

◆ thread_subvol_info_success

bool Main.thread_subvol_info_success = false

Definition at line 112 of file Main.vala.

Referenced by query_subvolume_info(), and query_subvolume_info_thread().

◆ update_grub

bool Main.update_grub = true

◆ update_initramfs

bool Main.update_initramfs = false

◆ use_option_raw

bool Main.use_option_raw = true

Definition at line 142 of file Main.vala.

Referenced by query_subvolume_quota().

◆ users_with_encrypted_home

string Main.users_with_encrypted_home = ""

Definition at line 165 of file Main.vala.

Referenced by detect_encrypted_dirs().

Property Documentation

◆ btrfs_qgroups_enabled

bool Main.btrfs_qgroups_enabled
get

Definition at line 181 of file Main.vala.

182 {
183 get { return _btrfs_qgroups_enabled_internal == QGroupStatus.ENABLED; }
184 }

Referenced by SnapshotRow.build_meta_text(), and Subvolume.remove().

◆ dst_boot

Device? Main.dst_boot
getset

Definition at line 1967 of file Main.vala.

1967 {
1968 get {
1969 foreach(var mnt in mount_list){
1970 if (mnt.mount_point == "/boot"){
1971 return mnt.device;
1972 }
1973 }
1974 return null;
1975 }
1976 set{
1977 foreach(var mnt in mount_list){
1978 if (mnt.mount_point == "/boot"){
1979 mnt.device = value;
1980 break;
1981 }
1982 }
1983 }
1984 }

◆ dst_efi

Device? Main.dst_efi
getset

Definition at line 1986 of file Main.vala.

1986 {
1987 get {
1988 foreach(var mnt in mount_list){
1989 if (mnt.mount_point == "/boot/efi"){
1990 return mnt.device;
1991 }
1992 }
1993 return null;
1994 }
1995 set{
1996 foreach(var mnt in mount_list){
1997 if (mnt.mount_point == "/boot/efi"){
1998 mnt.device = value;
1999 break;
2000 }
2001 }
2002 }
2003 }

◆ dst_home

Device? Main.dst_home
getset

Definition at line 2005 of file Main.vala.

2005 {
2006 get {
2007 foreach(var mnt in mount_list){
2008 if (mnt.mount_point == "/home"){
2009 return mnt.device;
2010 }
2011 }
2012 return null;
2013 }
2014 set{
2015 foreach(var mnt in mount_list){
2016 if (mnt.mount_point == "/home"){
2017 mnt.device = value;
2018 break;
2019 }
2020 }
2021 }
2022 }

Referenced by RestoreDeviceBox.check_and_mount_devices(), and mount_target_devices().

◆ dst_root

Device? Main.dst_root
getset

Definition at line 1948 of file Main.vala.

1948 {
1949 get {
1950 foreach(var mnt in mount_list){
1951 if (mnt.mount_point == "/"){
1952 return mnt.device;
1953 }
1954 }
1955 return null;
1956 }
1957 set{
1958 foreach(var mnt in mount_list){
1959 if (mnt.mount_point == "/"){
1960 mnt.device = value;
1961 break;
1962 }
1963 }
1964 }
1965 }

Referenced by RestoreDeviceBox.check_and_mount_devices(), init_boot_options(), init_mount_list(), AppConsole.map_devices(), mount_target_devices(), AppConsole.read_stdin_device_mounts(), and restore_snapshot().

◆ restore_current_system

bool Main.restore_current_system
get

Definition at line 2024 of file Main.vala.

2024 {
2025 get {
2026 if ((sys_root != null) &&
2027 ((dst_root != null && dst_root.device == sys_root.device) || (dst_root != null && dst_root.uuid == sys_root.uuid))){
2028
2029 return true;
2030 }
2031 else{
2032 return false;
2033 }
2034 }
2035 }

Referenced by check_and_repair_filesystems(), create_pre_restore_snapshot_btrfs(), create_restore_scripts(), get_restore_messages(), RestoreBox.restore(), restore_execute_btrfs(), restore_execute_rsync(), restore_snapshot(), and RestoreFinishBox.update_message().

◆ restore_exclude_file

string Main.restore_exclude_file
get

Definition at line 2067 of file Main.vala.

2067 {
2068 owned get {
2069 return restore_source_path + "/exclude-restore.list";
2070 }
2071 }

Referenced by create_restore_scripts(), restore_other_gui(), and save_exclude_list_for_restore().

◆ restore_log_file

string Main.restore_log_file
get

Definition at line 2061 of file Main.vala.

2061 {
2062 owned get {
2063 return restore_source_path + "/rsync-log-restore";
2064 }
2065 }

Referenced by create_restore_scripts(), restore_execute_rsync(), restore_other_console(), and restore_other_gui().

◆ restore_source_path

string Main.restore_source_path
get

Definition at line 2037 of file Main.vala.

2037 {
2038 owned get {
2039 if (mirror_system){
2040 string source_path = "/tmp/bastionguard-backup";
2041 dir_create(source_path);
2042 return source_path;
2043 }
2044 else{
2046 }
2047 }
2048 }

Referenced by create_restore_scripts(), and restore_execute_rsync().

◆ restore_target_path

string Main.restore_target_path
get

Definition at line 2050 of file Main.vala.

2050 {
2051 owned get {
2053 return "/";
2054 }
2055 else{
2056 return mount_point_restore + "/";
2057 }
2058 }
2059 }

Referenced by create_restore_scripts(), restore_execute_rsync(), restore_other_console(), and restore_other_gui().

◆ scheduled

bool Main.scheduled
get

Definition at line 1050 of file Main.vala.

1050 {
1051 get{
1052 return !live_system()
1055 }
1056 }

Referenced by create_snapshot(), cron_job_update(), FinishBox.refresh(), ScheduleBox.ScheduleBox(), and ScheduleBox.update_statusbar().


The documentation for this class was generated from the following file:
  • BastionGuard/thirdparty/bastionguard-backup/src/Core/Main.vala