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

Public Member Functions

SnapshotRepo. from_path (string path, Gtk.Window? parent_win, bool _btrfs_mode)
SnapshotRepo. from_device (Device dev, Gtk.Window? parent_win, bool btrfs_repo)
SnapshotRepo. from_uuid (string uuid, Gtk.Window? parent_win, bool btrfs_repo)
SnapshotRepo. from_null ()
bool unlock_and_mount_devices ()
string unlock_and_mount_device (Device device_to_mount, string path_to_mount)
Device? unlock_encrypted_device (Device luks_device)
bool load_snapshots ()
Gee.ArrayList< Snapshot?> get_snapshots_by_tag (string tag="")
Snapshot? get_latest_snapshot (string tag, string sys_uuid)
Snapshot? get_oldest_snapshot (string tag, string sys_uuid)
void check_status ()
bool available ()
bool has_btrfs_system ()
bool has_snapshots ()
bool has_space (uint64 needed=0)
void print_status ()
void auto_remove ()
void remove_untagged ()
void remove_marked_for_deletion ()
void remove_invalid ()
bool remove_all ()
bool remove_sync_dir ()
bool remove_timeshift_dir ()
void create_symlinks ()
void cleanup_symlink_dir (string tag)

Public Attributes

Device device = null
Device device_home = null
string mount_path = ""
Gee.HashMap< string, string > mount_paths
bool btrfs_mode = false
Gee.ArrayList< Snapshot?> snapshots
Gee.ArrayList< Snapshot?> invalid_snapshots
string status_message = ""
string status_details = ""
SnapshotLocationStatus status_code
bool last_snapshot_failed_space = false

Properties

string timeshift_path [get]
string snapshots_path [get]

Private Member Functions

void init_from_device ()
bool delete_directory (string dir_path)
void delete_directory_thread ()

Static Private Member Functions

static ? Device build_synthetic_device_for_path (string path)

Private Attributes

Gtk.? Window parent_window = null
bool thr_success = false
bool thr_running = false
string thr_args1 = ""

Detailed Description

Definition at line 32 of file SnapshotRepo.vala.

Member Function Documentation

◆ auto_remove()

void SnapshotRepo.auto_remove ( )
inline

Definition at line 686 of file SnapshotRepo.vala.

686 {
687
688 log_debug("SnapshotRepo: auto_remove()");
690 DateTime now = new DateTime.now_local();
691 DateTime dt_limit;
692 int count_limit;
693
694 // remove tags from older backups - boot ---------------
695
696 var list = get_snapshots_by_tag("boot");
697
698 if (list.size > App.count_boot){
699 log_msg(_("Maximum backups exceeded for backup level") + " '%s'".printf("boot"));
700 while (list.size > App.count_boot){
701 list[0].remove_tag("boot");
702 log_msg(_("Snapshot") + " '%s' ".printf(list[0].name) + _("un-tagged") + " '%s'".printf("boot"));
703 list = get_snapshots_by_tag("boot");
704 }
705 }
706
707 // remove tags from older backups - hourly, daily, weekly, monthly ---------
708
709 string[] levels = { "hourly","daily","weekly","monthly" };
710
711 foreach(string level in levels){
712
713 list = get_snapshots_by_tag(level);
714
715 if (list.size == 0) { continue; }
716
717 switch (level){
718 case "hourly":
719 dt_limit = now.add_hours(-1 * App.count_hourly);
720 count_limit = App.count_hourly;
721 break;
722 case "daily":
723 dt_limit = now.add_days(-1 * App.count_daily);
724 count_limit = App.count_daily;
725 break;
726 case "weekly":
727 dt_limit = now.add_weeks(-1 * App.count_weekly);
728 count_limit = App.count_weekly;
729 break;
730 case "monthly":
731 dt_limit = now.add_months(-1 * App.count_monthly);
732 count_limit = App.count_monthly;
733 break;
734 default:
735 dt_limit = now.add_years(-1 * 10);
736 count_limit = 100000;
737 break;
738 }
739
740 if (list.size > count_limit){
741
742 log_msg(_("Maximum backups exceeded for backup level") + " '%s'".printf(level));
743
744 int snaps_count = list.size;
745
746 foreach(var snap in list){
747
748 if (snap.description.strip().length > 0){ continue; } // don't delete snapshots with comments
749
750 if ((snap.date.compare(dt_limit) < 0) && (snaps_count > count_limit)){
751
752 snap.remove_tag(level);
753 snaps_count--;
754
755 log_msg(_("Snapshot") + " '%s' ".printf(list[0].name) + _("un-tagged") + " '%s'".printf(level));
756 }
757 }
758 }
759 }
760
761 // remove tags from older backups - max days -------
762
763 /*show_msg = true;
764 count = 0;
765 foreach(var bak in snapshots){
766 if (bak.date.compare(now.add_days(-1 * App.retain_snapshots_max_days)) < 0){
767 if (!bak.has_tag("ondemand")){
768
769 if (show_msg){
770 log_msg(_("Removing backups older than") + " %d ".printf(
771 App.retain_snapshots_max_days) + _("days..."));
772 show_msg = false;
773 }
774
775 log_msg(_("Snapshot") + " '%s' ".printf(bak.name) + _("un-tagged"));
776 bak.tags.clear();
777 count++;
778 }
779 }
780 }*/
781
782 // delete untagged snapshots
783
785
786 // delete older backups - minimum space -------
787
788 /*
789 device.query_disk_space();
790
791 show_msg = true;
792 count = 0;
793 while ((device.size_bytes - device.used_bytes) < App.minimum_free_disk_space){
794
795 load_snapshots();
796
797 if (snapshots.size > 0){
798 if (!snapshots[0].has_tag("ondemand")){
799
800 if (show_msg){
801 log_msg(_("Free space is less than") + " %lld GB".printf(
802 Main.MIN_FREE_SPACE / GB));
803 log_msg(_("Removing older backups to free disk space"));
804 show_msg = false;
805 }
806
807 snapshots[0].remove();
808 }
809 }
810
811 device.query_disk_space();
812 }
813 * */
814
815 // delete snapshots marked for deletion
816
818
819 // delete invalid snapshots
820
822 }
Main App
#define _(s)
int count_monthly
Definition Main.vala:92
int count_hourly
Definition Main.vala:95
int count_boot
Definition Main.vala:96
int count_weekly
Definition Main.vala:93
int count_daily
Definition Main.vala:94
bool last_snapshot_failed_space
void remove_marked_for_deletion()
void remove_untagged()
Gee.ArrayList< Snapshot?> get_snapshots_by_tag(string tag="")
void remove_invalid()
void log_debug(string message)
void log_msg(string message, bool highlight=false)

References _, App, Main.count_boot, Main.count_daily, Main.count_hourly, Main.count_monthly, Main.count_weekly, get_snapshots_by_tag(), last_snapshot_failed_space, TeeJee.Logging.log_debug(), TeeJee.Logging.log_msg(), remove_invalid(), remove_marked_for_deletion(), and remove_untagged().

Referenced by Main.create_snapshot().

◆ available()

bool SnapshotRepo.available ( )
inline

Definition at line 533 of file SnapshotRepo.vala.

533 {
534
535 log_debug("SnapshotRepo: available()");
536
537 //log_debug("checking selected device");
538
539 if (device == null){
540 if (App.backup_uuid == null || App.backup_uuid.length == 0){
541 log_debug("device is null");
542 status_message = _("Snapshot device not selected");
543 status_details = _("Select the snapshot device");
544 status_code = SnapshotLocationStatus.NOT_SELECTED;
545 log_debug("is_available: false");
546 return false;
547 }
548 else{
549 status_message = _("Snapshot device not available");
550 status_details = _("Device not found") + ": UUID='%s'".printf(App.backup_uuid);
551 status_code = SnapshotLocationStatus.NOT_AVAILABLE;
552 log_debug("is_available: false");
553 return false;
554 }
555 }
556 else{
557 if (btrfs_mode){
558 bool ok = has_btrfs_system();
559 if (ok){
560 log_debug("is_available: ok");
561 }
562 return ok;
563 }
564 else{
565 log_debug("is_available: ok");
566 return true;
567 }
568 }
569 }
SnapshotLocationStatus
string backup_uuid
Definition Main.vala:49
bool has_btrfs_system()
string status_details
string status_message
SnapshotLocationStatus status_code

References _, App, Main.backup_uuid, btrfs_mode, device, has_btrfs_system(), TeeJee.Logging.log_debug(), status_code, status_details, and status_message.

Referenced by check_status(), MainWindow.create_snapshot(), Main.create_snapshot_for_tag(), MainWindow.delete_selected(), BackupWindow.go_first(), BackupWindow.go_prev(), MainWindow.init_delayed(), MainWindow.on_close_request(), SnapshotListBox.refresh(), Main.save_app_config(), AppConsole.select_snapshot_device(), Main.try_select_default_device_for_backup(), BackupWindow.validate_current_tab(), and SetupWizardWindow.validate_current_tab().

◆ build_synthetic_device_for_path()

? Device SnapshotRepo.build_synthetic_device_for_path ( string path)
inlinestaticprivate

Definition at line 90 of file SnapshotRepo.vala.

90 {
91 string std_out, std_err;
92 int rc = exec_sync("df -T -B1 \"%s\"".printf(path), out std_out, out std_err);
93 if (rc != 0){ return null; }
94
95 string[] lines = std_out.split("\n");
96 if (lines.length < 2){ return null; }
97
98 // Take the last non-empty line — this is the data row
99 string data_line = "";
100 for (int i = lines.length - 1; i >= 1; i--){
101 if (lines[i].strip().length > 0){ data_line = lines[i]; break; }
102 }
103 if (data_line.length == 0){ return null; }
104
105 var dev = new Device();
106 int k = 1;
107 foreach (string val in data_line.split(" ")){
108 if (val.strip().length == 0){ continue; }
109 switch (k++){
110 case 1: dev.device = val.strip(); break;
111 case 2: dev.fstype = val.strip(); break;
112 case 3: dev.size_bytes = uint64.parse(val.strip()); break;
113 case 4: dev.used_bytes = uint64.parse(val.strip()); break;
114 case 5: dev.available_bytes = uint64.parse(val.strip()); break;
115 case 6: dev.used_percent = val.strip(); break;
116 }
117 }
118 // Synthetic non-empty UUID so downstream code that checks
119 // `device != null && device.uuid.length > 0` keeps working.
120 // We deliberately use a "sha:" prefix that no real UUID can have.
121 dev.uuid = "smb:%s".printf(path);
122 dev.type = "remote";
123 return dev;
124 }
Device()
Definition Device.vala:94
int exec_sync(string cmd, out string? std_out=null, out string? std_err=null)

References Device.Device(), and TeeJee.ProcessHelper.exec_sync().

Referenced by from_path().

◆ check_status()

void SnapshotRepo.check_status ( )
inline

Definition at line 491 of file SnapshotRepo.vala.

491 {
492
493 log_debug("SnapshotRepo: check_status()");
494
496 {
497 status_code = SnapshotLocationStatus.HAS_SNAPSHOTS_HAS_SPACE;
498 status_message = "";
499 status_details = "";
500 }
501
502 if (available()){
505 {
506 has_space();
507 }
508 }
509
510 if ((App != null) && (App.app_mode.length == 0)){
511
512 log_debug("%s: '%s'".printf(
513 _("Snapshot device"),
514 (device == null) ? " UNKNOWN" : device.device));
515
516 log_debug("%s: %s".printf(
517 _("Snapshot location"), mount_path));
518
521
522 log_debug("%s: %s".printf(
523 _("Status"),
524 status_code.to_string().replace("SNAPSHOT_LOCATION_STATUS_","")));
525
526 log_debug("");
527 }
528
530 log_debug("SnapshotRepo: check_status(): exit");
531 }
string device
Definition Device.vala:44
string app_mode
Definition Main.vala:98
bool has_space(uint64 needed=0)

References _, App, Main.app_mode, available(), Device.device, device, has_snapshots(), has_space(), last_snapshot_failed_space, TeeJee.Logging.log_debug(), mount_path, status_code, status_details, and status_message.

Referenced by BackupDeviceBox.check_backup_location(), Main.check_backup_location(), from_path(), init_from_device(), print_status(), and MainWindow.update_statusbar().

◆ cleanup_symlink_dir()

void SnapshotRepo.cleanup_symlink_dir ( string tag)
inline

Definition at line 998 of file SnapshotRepo.vala.

998 {
999 try{
1000 string path = "%s-%s".printf(snapshots_path, tag);
1001 if(!TeeJee.FileSystem.dir_delete_recursive(path)) {
1002 log_error(_("Failed to delete symlinks") + ": '%s'".printf(path));
1003 }
1004
1005 File f = File.new_for_path(path);
1006 f.make_directory_with_parents();
1007 }
1008 catch (Error e) {
1009 log_error (e.message);
1010 }
1011 }
string snapshots_path
void log_error(string message, bool highlight=false, bool is_warning=false)

References _, Error, TeeJee.Logging.log_error(), and snapshots_path.

Referenced by create_symlinks().

◆ create_symlinks()

void SnapshotRepo.create_symlinks ( )
inline

Definition at line 970 of file SnapshotRepo.vala.

970 {
971 cleanup_symlink_dir("boot");
972 cleanup_symlink_dir("hourly");
973 cleanup_symlink_dir("daily");
974 cleanup_symlink_dir("weekly");
975 cleanup_symlink_dir("monthly");
976 cleanup_symlink_dir("ondemand");
977
978
979 foreach(Snapshot bak in snapshots){
980 foreach(string tag in bak.tags) {
981 string linkTarget = "%s-%s/%s".printf(snapshots_path, tag, bak.name);
982 string linkValue = "../snapshots/" + bak.name;
983 try {
984 File f = File.new_for_path(linkTarget);
985 if (!f.make_symbolic_link(linkValue)) {
986 log_error(_("Failed to create symlinks") + ": %s".printf(linkTarget));
987 }
988 } catch(Error e) {
989 log_debug(e.message);
990 log_error(_("Failed to create symlinks") + ": %s".printf(linkTarget));
991 }
992 }
993 }
994
995 log_debug (_("Symlinks updated"));
996 }
void cleanup_symlink_dir(string tag)
Gee.ArrayList< Snapshot?> snapshots
string name
Definition Snapshot.vala:37
Gee.ArrayList< string > tags
Definition Snapshot.vala:44

References _, cleanup_symlink_dir(), Error, TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), snapshots, and snapshots_path.

Referenced by Main.create_snapshot().

◆ delete_directory()

bool SnapshotRepo.delete_directory ( string dir_path)
inlineprivate

Definition at line 933 of file SnapshotRepo.vala.

933 {
934 thr_args1 = dir_path;
935
936 try {
937 thr_running = true;
938 thr_success = false;
939 new Thread<void>.try ("delete-directory", () => {delete_directory_thread();});
940 } catch (Error e) {
941 thr_running = false;
942 thr_success = false;
943 log_error (e.message);
944 }
945
946 while (thr_running){
947 gtk_do_events ();
948 Thread.usleep((ulong) GLib.TimeSpan.MILLISECOND * 100);
949 }
950
951 thr_args1 = null;
952
953 return thr_success;
954 }
void delete_directory_thread()

References delete_directory_thread(), Error, TeeJee.GtkHelper.gtk_do_events(), TeeJee.Logging.log_error(), thr_args1, thr_running, and thr_success.

Referenced by remove_all(), remove_sync_dir(), and remove_timeshift_dir().

◆ delete_directory_thread()

void SnapshotRepo.delete_directory_thread ( )
inlineprivate

Definition at line 956 of file SnapshotRepo.vala.

956 {
957 thr_success = TeeJee.FileSystem.dir_delete_recursive(thr_args1);
958
959 if (thr_success) {
960 log_msg(_("Removed") + ": '%s'".printf(thr_args1));
961 } else{
962 log_error(_("Failed to remove") + ": '%s'".printf(thr_args1));
963 }
964
965 thr_running = false;
966 }

References _, TeeJee.Logging.log_error(), TeeJee.Logging.log_msg(), thr_args1, thr_running, and thr_success.

Referenced by delete_directory().

◆ from_device()

SnapshotRepo. SnapshotRepo.from_device ( Device dev,
Gtk.Window? parent_win,
bool btrfs_repo )
inline

Definition at line 126 of file SnapshotRepo.vala.

126 {
127
128 log_debug("SnapshotRepo: from_device(): %s".printf(btrfs_repo ? "BTRFS" : "RSYNC"));
129
130 this.device = dev;
131 //this.use_snapshot_path_custom = false;
132 this.parent_window = parent_win;
133 this.btrfs_mode = btrfs_repo;
134
135 snapshots = new Gee.ArrayList<Snapshot>();
136 invalid_snapshots = new Gee.ArrayList<Snapshot>();
137 mount_paths = new Gee.HashMap<string,string>();
138
140 }
void init_from_device()
Gee.ArrayList< Snapshot?> invalid_snapshots
Gee.HashMap< string, string > mount_paths

References init_from_device(), invalid_snapshots, TeeJee.Logging.log_debug(), mount_paths, and snapshots.

Referenced by BackupDeviceBox.change_backup_device(), Main.initialize_repo(), AppConsole.select_snapshot_device(), and Main.try_select_default_device_for_backup().

◆ from_null()

SnapshotRepo. SnapshotRepo.from_null ( )
inline

Definition at line 166 of file SnapshotRepo.vala.

166 {
167
168 log_debug("SnapshotRepo: from_null()");
169 log_debug("device not set");
170
171 snapshots = new Gee.ArrayList<Snapshot>();
172 invalid_snapshots = new Gee.ArrayList<Snapshot>();
173 mount_paths = new Gee.HashMap<string,string>();
174
175 log_debug("SnapshotRepo: from_null(): exit");
176 }

References invalid_snapshots, TeeJee.Logging.log_debug(), mount_paths, and snapshots.

Referenced by MainWindow.settings_changed(), and Main.try_select_default_device_for_backup().

◆ from_path()

SnapshotRepo. SnapshotRepo.from_path ( string path,
Gtk.Window? parent_win,
bool _btrfs_mode )
inline

Definition at line 54 of file SnapshotRepo.vala.

54 {
55
56 log_debug("SnapshotRepo: from_path()");
57
58 this.mount_path = path;
59 this.parent_window = parent_win;
60 this.btrfs_mode = _btrfs_mode;
61
62 snapshots = new Gee.ArrayList<Snapshot>();
63 invalid_snapshots = new Gee.ArrayList<Snapshot>();
64 mount_paths = new Gee.HashMap<string,string>();
65
66 //log_debug("Selected snapshot repo path: %s".printf(path));
67
68 var list = Device.get_disk_space_using_df(path);
69
70 if (list.size > 0){
71
72 device = list[0];
73
74 log_debug(_("Device") + ": %s".printf(device.device));
75 log_debug(_("Free space") + ": %s".printf(format_file_size(device.free_bytes)));
76 }
77 else {
78 // Fall back for filesystems that have no block-device UUID
79 // (CIFS/SMB, NFS, sshfs, …). We synthesise a Device so the
80 // rest of the code can carry on uniformly.
82 if (device != null){
83 log_debug("SnapshotRepo: from_path(): synthetic device for path %s".printf(path));
84 }
85 }
86
88 }
uint64 free_bytes
Definition Device.vala:120
static ? Device build_synthetic_device_for_path(string path)
string format_file_size(uint64 size, bool binary_units=false, string unit="", bool show_units=true, int decimals=1)

References _, build_synthetic_device_for_path(), check_status(), Device.device, device, TeeJee.FileSystem.format_file_size(), Device.free_bytes, Device.get_disk_space_using_df(), invalid_snapshots, TeeJee.Logging.log_debug(), mount_paths, and snapshots.

Referenced by BackupDeviceBox.try_change_smb_share().

◆ from_uuid()

SnapshotRepo. SnapshotRepo.from_uuid ( string uuid,
Gtk.Window? parent_win,
bool btrfs_repo )
inline

Definition at line 142 of file SnapshotRepo.vala.

142 {
143
144 log_debug("SnapshotRepo: from_uuid(): %s".printf(btrfs_repo ? "BTRFS" : "RSYNC"));
145 log_debug("uuid=%s".printf(uuid));
146
147 device = Device.get_device_by_uuid(uuid);
148 if (device == null){
149 device = new Device();
150 device.uuid = uuid;
151 }
152
153 //this.use_snapshot_path_custom = false;
154 this.parent_window = parent_win;
155 this.btrfs_mode = btrfs_repo;
156
157 snapshots = new Gee.ArrayList<Snapshot>();
158 invalid_snapshots = new Gee.ArrayList<Snapshot>();
159 mount_paths = new Gee.HashMap<string,string>();
160
162
163 log_debug("SnapshotRepo: from_uuid(): exit");
164 }
static ? Device get_device_by_uuid(string uuid)
Definition Device.vala:1081

References Device.Device(), device, Device.get_device_by_uuid(), init_from_device(), invalid_snapshots, TeeJee.Logging.log_debug(), mount_paths, and snapshots.

Referenced by MainWindow.init_delayed(), Main.initialize_repo(), SetupWizardWindow.probe_timeshift_snapshot_count(), SetupWizardWindow.probe_timeshift_snapshots_from_mounts(), and MainWindow.settings_changed().

◆ get_latest_snapshot()

Snapshot? SnapshotRepo.get_latest_snapshot ( string tag,
string sys_uuid )
inline

Definition at line 461 of file SnapshotRepo.vala.

461 {
462
463 var list = get_snapshots_by_tag(tag);
464
465 for(int i = list.size - 1; i >= 0; i--){
466 var bak = list[i];
467 if (bak.sys_uuid == sys_uuid){
468 return bak;
469 }
470 }
471
472 return null;
473 }

References get_snapshots_by_tag().

Referenced by Main.create_snapshot(), Main.create_snapshot_with_rsync(), and Main.get_space_needed_for_rsync_snapshot().

◆ get_oldest_snapshot()

Snapshot? SnapshotRepo.get_oldest_snapshot ( string tag,
string sys_uuid )
inline

Definition at line 475 of file SnapshotRepo.vala.

475 {
476
477 var list = get_snapshots_by_tag(tag);
478
479 for(int i = 0; i < list.size; i++){
480 var bak = list[i];
481 if (bak.sys_uuid == sys_uuid){
482 return bak;
483 }
484 }
485
486 return null;
487 }

References get_snapshots_by_tag().

◆ get_snapshots_by_tag()

Gee.ArrayList< Snapshot?> SnapshotRepo.get_snapshots_by_tag ( string tag = "")
inline

Definition at line 443 of file SnapshotRepo.vala.

443 {
444
445 var list = new Gee.ArrayList<Snapshot?>();
446
447 foreach(Snapshot bak in snapshots){
448 if (bak.valid && (tag.length == 0) || bak.has_tag(tag)){
449 list.add(bak);
450 }
451 }
452 list.sort((a,b) => {
453 Snapshot t1 = (Snapshot) a;
454 Snapshot t2 = (Snapshot) b;
455 return (t1.date.compare(t2.date));
456 });
457
458 return list;
459 }
DateTime date
Definition Snapshot.vala:38
bool has_tag(string tag)
bool valid
Definition Snapshot.vala:49

References Snapshot.date, and snapshots.

Referenced by auto_remove(), get_latest_snapshot(), and get_oldest_snapshot().

◆ has_btrfs_system()

bool SnapshotRepo.has_btrfs_system ( )
inline

Definition at line 571 of file SnapshotRepo.vala.

571 {
572
573 log_debug("SnapshotRepo: has_btrfs_system()");
574
575 var root_path = path_combine(mount_paths["@"],"@");
576 log_debug("root_path=%s".printf(root_path));
577 log_debug("btrfs_mode=%s".printf(btrfs_mode.to_string()));
578 if (btrfs_mode){
579 if (!dir_exists(root_path)){
580 status_message = _("Selected snapshot device is not a system disk");
581 status_details = _("Select BTRFS system disk with root subvolume (@)");
582 status_code = SnapshotLocationStatus.NO_BTRFS_SYSTEM;
584 return false;
585 }
586 }
587
588 return true;
589 }
string path_combine(string path1, string path2)
bool dir_exists(string dir_path)

References _, btrfs_mode, TeeJee.FileSystem.dir_exists(), TeeJee.Logging.log_debug(), mount_paths, TeeJee.FileSystem.path_combine(), status_code, status_details, and status_message.

Referenced by available().

◆ has_snapshots()

bool SnapshotRepo.has_snapshots ( )
inline

Definition at line 591 of file SnapshotRepo.vala.

591 {
592
593 log_debug("SnapshotRepo: has_snapshots()");
594
595 //load_snapshots();
596 return (snapshots.size > 0);
597 }

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

Referenced by check_status(), MainWindow.delete_selected(), Main.save_app_config(), AppConsole.select_snapshot(), and AppConsole.start_application().

◆ has_space()

bool SnapshotRepo.has_space ( uint64 needed = 0)
inline

Definition at line 599 of file SnapshotRepo.vala.

599 {
600 log_debug("SnapshotRepo: has_space() - %llu required (%s)".printf(needed, format_file_size(needed)));
601
602 if ((device != null) && (device.device.length > 0)){
604 }
605 else{
606 log_debug("device is NULL");
607 return false;
608 }
609
610 if (snapshots.size > 0){
611 // has snapshots, check minimum space
612
613 if (device.free_bytes < (needed > 0 ? needed : Main.MIN_FREE_SPACE)) {
614 status_message = _("Not enough disk space");
615 status_message += " (< %s)".printf(format_file_size((needed > 0 ? needed : Main.MIN_FREE_SPACE), false, "", true, 0));
616
617 status_details = _("Select another device or free up some space");
618
619 status_code = SnapshotLocationStatus.HAS_SNAPSHOTS_NO_SPACE;
621 return false;
622 }
623 else{
624 //ok
625 status_message = _("OK");
626
627 status_details = _("%d snapshots, %s free").printf(
629
631 status_code = SnapshotLocationStatus.HAS_SNAPSHOTS_HAS_SPACE;
632 return true;
633 }
634 }
635 else {
636
637 // no snapshots, check estimated space
638 log_debug("no snapshots");
639
640 var required_space = Main.first_snapshot_size;
641
642 if (device.free_bytes < required_space){
643 status_message = _("Not enough disk space");
644 status_message += " (< %s)".printf(format_file_size(required_space));
645
646 status_details = _("Select another device or free up some space");
647
648 status_code = SnapshotLocationStatus.NO_SNAPSHOTS_NO_SPACE;
649 return false;
650 }
651 else{
652 status_message = _("No snapshots on this device");
653
654 status_details = _("First snapshot requires:");
655 status_details += " %s".printf(format_file_size(required_space));
656
657 status_code = SnapshotLocationStatus.NO_SNAPSHOTS_HAS_SPACE;
658 return true;
659 }
660 }
661 }
void query_disk_space()
Definition Device.vala:1285

References _, Device.device, device, Main.first_snapshot_size, TeeJee.FileSystem.format_file_size(), Device.free_bytes, last_snapshot_failed_space, TeeJee.Logging.log_debug(), Main.MIN_FREE_SPACE, Device.query_disk_space(), snapshots, status_code, status_details, and status_message.

Referenced by check_status(), Main.create_snapshot(), Main.create_snapshot_for_tag(), BackupWindow.go_first(), BackupWindow.go_prev(), MainWindow.on_close_request(), BackupWindow.validate_current_tab(), and SetupWizardWindow.validate_current_tab().

◆ init_from_device()

void SnapshotRepo.init_from_device ( )
inlineprivate

Definition at line 178 of file SnapshotRepo.vala.

178 {
179
180 log_debug("SnapshotRepo: init_from_device()");
181
182 if ((device != null) && (device.uuid.length > 0) && (Device.get_device_by_uuid(device.uuid) != null)){
183
184 log_debug("");
186
187 if ((device != null) && (device.device.length > 0)){
188
189 log_debug(_("Selected snapshot device") + ": %s".printf(device.device));
190 log_debug(_("Free space") + ": %s".printf(format_file_size(device.free_bytes)));
191 }
192 }
193
194 if ((device != null) && (device.device.length > 0)){
195
196 check_status();
197 }
198
199 log_debug("SnapshotRepo: init_from_device(): exit");
200 }
string uuid
Definition Device.vala:50
bool unlock_and_mount_devices()

References _, check_status(), Device.device, device, TeeJee.FileSystem.format_file_size(), Device.free_bytes, Device.get_device_by_uuid(), TeeJee.Logging.log_debug(), unlock_and_mount_devices(), and Device.uuid.

Referenced by from_device(), and from_uuid().

◆ load_snapshots()

bool SnapshotRepo.load_snapshots ( )
inline

Definition at line 363 of file SnapshotRepo.vala.

363 {
364
365 log_debug("SnapshotRepo: load_snapshots()");
366
367 snapshots.clear();
368 invalid_snapshots.clear();
369
370 if ((device == null) || !dir_exists(snapshots_path)){
371 return false;
372 }
373
374 try{
375 var dir = File.new_for_path(snapshots_path);
376 var enumerator = dir.enumerate_children("*", 0);
377
378 var info = enumerator.next_file ();
379 while (info != null) {
380 if (info.get_file_type() == FileType.DIRECTORY) {
381 if (info.get_name() != ".sync") {
382
383 //log_debug("load_snapshots():" + snapshots_path + "/" + info.get_name());
384
385 Snapshot bak = new Snapshot(snapshots_path + "/" + info.get_name(), btrfs_mode, this);
386 if (bak.valid){
387 snapshots.add(bak);
388 }
389 else{
390 invalid_snapshots.add(bak);
391 }
392 }
393 }
394 info = enumerator.next_file ();
395 }
396 }
397 catch(Error e){
398 log_error (e.message);
399 return false;
400 }
401
402 snapshots.sort((a,b) => {
403 Snapshot t1 = (Snapshot) a;
404 Snapshot t2 = (Snapshot) b;
405 return t1.date.compare(t2.date);
406 });
407
408 // reset the 'live' flag ------------
409
410 DateTime dt_boot = new DateTime.now_local();
411 dt_boot = dt_boot.add_seconds(-1.0 * get_system_uptime_seconds());
412 foreach(var bak in snapshots){
413 if (bak.live){
414 if ((App.sys_root == null) || (App.sys_root.uuid != bak.sys_uuid)){
415 // we are accessing the snapshot from a live system or another system
416 bak.live = false;
417 bak.update_control_file();
418 }
419 else{
420 if (bak.date.difference(dt_boot) < 0){
421 // snapshot was created before the last reboot
422 bak.live = false;
423 bak.update_control_file();
424 }
425 else{
426 // do nothing, snapshot is still in use by system
427 }
428 }
429 }
430 }
431
432 if (btrfs_mode){
434 }
435
436 log_debug("loading snapshots from '%s': %d found".printf(snapshots_path, snapshots.size));
437
438 return true;
439 }
Device sys_root
Definition Main.vala:75
void query_subvolume_info(SnapshotRepo parent_repo)
Definition Main.vala:4222
Snapshot(string dir_path, bool btrfs_snapshot, SnapshotRepo _repo)
Definition Snapshot.vala:63
double get_system_uptime_seconds()

References App, btrfs_mode, Snapshot.date, device, TeeJee.FileSystem.dir_exists(), Error, TeeJee.System.get_system_uptime_seconds(), invalid_snapshots, TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), Main.query_subvolume_info(), Snapshot.Snapshot(), snapshots, snapshots_path, Main.sys_root, Device.uuid, and Snapshot.valid.

Referenced by Main.create_pre_restore_snapshot_btrfs(), Main.create_snapshot(), MainWindow.mark_selected(), MainWindow.open_restore_flow(), SetupWizardWindow.probe_timeshift_snapshot_count(), SnapshotListBox.refresh(), remove_all(), remove_invalid(), remove_marked_for_deletion(), remove_untagged(), SetupWizardWindow.run_timeshift_import(), MainWindow.settings_changed(), and unlock_and_mount_devices().

◆ print_status()

void SnapshotRepo.print_status ( )
inline

Definition at line 663 of file SnapshotRepo.vala.

663 {
664
665 check_status();
666
667 //log_msg("");
668
669 if (device == null){
670 log_msg("%-6s : %s".printf(_("Device"), _("Not Selected")));
671 }
672 else{
673 log_msg("%-6s : %s".printf(_("Device"), device.device_name_with_parent));
674 log_msg("%-6s : %s".printf("UUID", device.uuid));
675 log_msg("%-6s : %s".printf(_("Path"), mount_path));
676 log_msg("%-6s : %s".printf(_("Mode"), btrfs_mode ? "BTRFS" : "RSYNC"));
677 log_msg("%-6s : %s".printf(_("Status"), status_message));
679 }
680
681 log_msg("");
682 }
string device_name_with_parent
Definition Device.vala:1813

References _, btrfs_mode, check_status(), device, Device.device_name_with_parent, TeeJee.Logging.log_msg(), mount_path, status_details, status_message, and Device.uuid.

Referenced by AppConsole.start_application().

◆ remove_all()

bool SnapshotRepo.remove_all ( )
inline

Definition at line 881 of file SnapshotRepo.vala.

881 {
882
884
885 log_msg(_("Removing snapshots") + " > " + _("all") + "...");
886
887 //delete snapshots
888 foreach(var bak in snapshots){
889 bak.remove(true);
890 }
891
893
895
896 load_snapshots(); // update the list
897
898 return ok;
899 }
900 else{
901 log_msg(_("No snapshots found") + " '%s'".printf(mount_path));
902 return true;
903 }
904 }
bool remove_sync_dir()
bool load_snapshots()
bool delete_directory(string dir_path)
string timeshift_path

References _, delete_directory(), TeeJee.FileSystem.dir_exists(), load_snapshots(), TeeJee.Logging.log_msg(), mount_path, remove_sync_dir(), snapshots, and timeshift_path.

◆ remove_invalid()

void SnapshotRepo.remove_invalid ( )
inline

Definition at line 864 of file SnapshotRepo.vala.

864 {
865
866 bool show_msg = true;
867
868 foreach(var bak in invalid_snapshots){
869
870 if (show_msg){
871 log_msg("%s (%s):".printf(_("Removing snapshots"), _("incomplete")));
872 show_msg = false;
873 }
874
875 bak.remove(true);
876 }
877
878 load_snapshots(); // update the list
879 }

References _, invalid_snapshots, load_snapshots(), and TeeJee.Logging.log_msg().

Referenced by auto_remove().

◆ remove_marked_for_deletion()

void SnapshotRepo.remove_marked_for_deletion ( )
inline

Definition at line 845 of file SnapshotRepo.vala.

845 {
846
847 bool show_msg = true;
848
849 foreach(var bak in snapshots){
850 if (bak.marked_for_deletion){
851
852 if (show_msg){
853 log_msg("%s (%s):".printf(_("Removing snapshots"), _("marked for deletion")));
854 show_msg = false;
855 }
856
857 bak.remove(true);
858 }
859 }
860
861 load_snapshots(); // update the list
862 }

References _, load_snapshots(), TeeJee.Logging.log_msg(), and snapshots.

Referenced by auto_remove().

◆ remove_sync_dir()

bool SnapshotRepo.remove_sync_dir ( )
inline

Definition at line 906 of file SnapshotRepo.vala.

906 {
907 string sync_dir = mount_path + "/bastionguard-backup/snapshots/.sync";
908
909 //delete .sync
910 if (dir_exists(sync_dir)){
911 if (!delete_directory(sync_dir)){
912 return false;
913 }
914 }
915
916 return true;
917 }

References delete_directory(), TeeJee.FileSystem.dir_exists(), and mount_path.

Referenced by remove_all().

◆ remove_timeshift_dir()

bool SnapshotRepo.remove_timeshift_dir ( )
inline

Definition at line 919 of file SnapshotRepo.vala.

919 {
920
921 // delete /bastionguard-backup
924 return false;
925 }
926 }
927
928 return true;
929 }

References delete_directory(), TeeJee.FileSystem.dir_exists(), and timeshift_path.

◆ remove_untagged()

void SnapshotRepo.remove_untagged ( )
inline

Definition at line 824 of file SnapshotRepo.vala.

824 {
825
826 log_debug("SnapshotRepo: remove_untagged()");
827
828 bool show_msg = true;
829
830 foreach(Snapshot bak in snapshots){
831 if (bak.tags.size == 0){
832
833 if (show_msg){
834 log_msg("%s (%s):".printf(_("Removing snapshots"), _("un-tagged")));
835 show_msg = false;
836 }
837
838 bak.remove(true);
839 }
840 }
841
842 load_snapshots(); // update the list
843 }
bool remove(bool wait)

References _, load_snapshots(), TeeJee.Logging.log_debug(), TeeJee.Logging.log_msg(), and snapshots.

Referenced by auto_remove().

◆ unlock_and_mount_device()

string SnapshotRepo.unlock_and_mount_device ( Device device_to_mount,
string path_to_mount )
inline

Definition at line 301 of file SnapshotRepo.vala.

301 {
302
303 // mounts the device and returns mount path
304
305 log_debug("SnapshotRepo: unlock_and_mount_device()");
306
307 Device dev = device_to_mount;
308
309 if (dev == null){
310 log_debug("device=null");
311 }
312 else{
313 log_debug("device=%s".printf(dev.device));
314 }
315
316 // unlock encrypted device
317 if (dev.is_encrypted_partition()){
318
319 dev = unlock_encrypted_device(dev);
320 device = dev; // set repo device to unlocked child disk
321
322 if (dev == null){
323 log_debug("device is null");
324 log_debug("SnapshotRepo: unlock_and_mount_device(): exit");
325 return "";
326 }
327 }
328
329 // mount
330 var mount_options = "";
331 if (btrfs_mode){
332 mount_options = "subvolid=0";
333 }
334 bool ok = Device.mount(dev.uuid, path_to_mount, mount_options); // TODO: check if already mounted
335
336 if (ok){
337 return path_to_mount;
338 }
339 else{
340 return "";
341 }
342 }
bool is_encrypted_partition()
Definition Device.vala:216
static bool mount(string dev_name_or_uuid, string mount_point, string mount_options="", bool silent=false)
Definition Device.vala:1571
Device? unlock_encrypted_device(Device luks_device)

References btrfs_mode, Device.device, device, Device.is_encrypted_partition(), TeeJee.Logging.log_debug(), Device.mount(), unlock_encrypted_device(), and Device.uuid.

Referenced by unlock_and_mount_devices().

◆ unlock_and_mount_devices()

bool SnapshotRepo.unlock_and_mount_devices ( )
inline

Definition at line 245 of file SnapshotRepo.vala.

245 {
246
247 log_debug("SnapshotRepo: unlock_and_mount_devices()");
248
249 if (device == null){
250 log_debug("device=null");
251 }
252 else{
253 log_debug("device=%s".printf(device.device));
254 }
255
257
258 if (mount_path.length == 0){
259 return false;
260 }
261
262 // rsync
263 mount_paths["@"] = "";
264 mount_paths["@home"] = "";
265
266 if (btrfs_mode){
267
268 mount_paths["@"] = mount_path;
269 mount_paths["@home"] = mount_path; //default
270 device_home = device; //default
271
272 // mount @home if on different disk -------
273
274 var repo_subvolumes = Subvolume.detect_subvolumes_for_system_by_path(path_combine(mount_path,"@"), this, parent_window);
275
276 if (repo_subvolumes.has_key("@home")){
277
278 var subvol = repo_subvolumes["@home"];
279
280 if (subvol.device_uuid != device.uuid){
281
282 // @home is on a separate device
283 device_home = subvol.get_device();
284
286
287 if (mount_paths["@home"].length == 0){
288 return false;
289 }
290 }
291 }
292 }
293
295
296 log_debug("SnapshotRepo: unlock_and_mount_device(): exit");
297
298 return true;
299 }
string mount_point_app
Definition Main.vala:82
Gtk.? Window parent_window
string unlock_and_mount_device(Device device_to_mount, string path_to_mount)

References App, btrfs_mode, Subvolume.detect_subvolumes_for_system_by_path(), Device.device, device, device_home, load_snapshots(), TeeJee.Logging.log_debug(), mount_path, mount_paths, Main.mount_point_app, parent_window, TeeJee.FileSystem.path_combine(), unlock_and_mount_device(), and Device.uuid.

Referenced by init_from_device().

◆ unlock_encrypted_device()

Device? SnapshotRepo.unlock_encrypted_device ( Device luks_device)
inline

Definition at line 344 of file SnapshotRepo.vala.

344 {
345
346 log_debug("SnapshotRepo: unlock_encrypted_device()");
347
348 if (luks_device == null){
349 log_debug("luks_device=null");
350 return null;
351 }
352 else{
353 log_debug("luks_device=%s".printf(luks_device.device));
354 }
355
356 string msg_out, msg_err;
357 var luks_unlocked = Device.luks_unlock(
358 luks_device, "", "", parent_window, out msg_out, out msg_err);
359
360 return luks_unlocked;
361 }

References Device.device, TeeJee.Logging.log_debug(), Device.luks_unlock(), and parent_window.

Referenced by unlock_and_mount_device().

Member Data Documentation

◆ btrfs_mode

◆ device

◆ device_home

◆ invalid_snapshots

Gee.ArrayList<Snapshot?> SnapshotRepo.invalid_snapshots

◆ last_snapshot_failed_space

bool SnapshotRepo.last_snapshot_failed_space = false

Definition at line 46 of file SnapshotRepo.vala.

Referenced by auto_remove(), check_status(), and has_space().

◆ mount_path

◆ mount_paths

◆ parent_window

Gtk.? Window SnapshotRepo.parent_window = null
private

Definition at line 49 of file SnapshotRepo.vala.

Referenced by unlock_and_mount_devices(), and unlock_encrypted_device().

◆ snapshots

◆ status_code

◆ status_details

◆ status_message

◆ thr_args1

string SnapshotRepo.thr_args1 = ""
private

Definition at line 52 of file SnapshotRepo.vala.

Referenced by delete_directory(), and delete_directory_thread().

◆ thr_running

bool SnapshotRepo.thr_running = false
private

Definition at line 51 of file SnapshotRepo.vala.

Referenced by delete_directory(), and delete_directory_thread().

◆ thr_success

bool SnapshotRepo.thr_success = false
private

Definition at line 50 of file SnapshotRepo.vala.

Referenced by delete_directory(), and delete_directory_thread().

Property Documentation

◆ snapshots_path

string SnapshotRepo.snapshots_path
get

◆ timeshift_path

string SnapshotRepo.timeshift_path
get

Definition at line 204 of file SnapshotRepo.vala.

204 {
205 owned get {
206 if (btrfs_mode) {
207 string bg_btrfs = path_combine(mount_path, "bastionguard-backup-btrfs");
208 if (dir_exists(bg_btrfs)) {
209 return bg_btrfs;
210 }
211
212 string legacy_btrfs = path_combine(mount_path, "timeshift-btrfs");
213 if (dir_exists(legacy_btrfs)) {
214 return legacy_btrfs;
215 }
216
217 /* Nessun repo esistente: usa il nuovo nome */
218 return bg_btrfs;
219 }
220 else {
221 string bg_path = path_combine(mount_path, "bastionguard-backup");
222 if (dir_exists(bg_path)) {
223 return bg_path;
224 }
225
226 string legacy_path = path_combine(mount_path, "timeshift");
227 if (dir_exists(legacy_path)) {
228 return legacy_path;
229 }
230
231 /* Nessun repo esistente: usa il nuovo nome */
232 return bg_path;
233 }
234 }
235 }

Referenced by remove_all(), and remove_timeshift_dir().


The documentation for this class was generated from the following file: