diff --git a/files/timeshift.json b/files/timeshift.json index 4d5a6910..0ccd86ea 100644 --- a/files/timeshift.json +++ b/files/timeshift.json @@ -3,6 +3,7 @@ "parent_device_uuid" : "", "do_first_run" : "true", "btrfs_mode" : "false", + "btrfs_readonly" : "true", "include_btrfs_home" : "false", "stop_cron_emails" : "true", "schedule_monthly" : "false", diff --git a/src/AppConsole.vala b/src/AppConsole.vala index a4554b77..014a19fa 100644 --- a/src/AppConsole.vala +++ b/src/AppConsole.vala @@ -160,6 +160,10 @@ public class AppConsole : GLib.Object { App.app_mode = "ondemand"; break; + case "--readonly": + App.btrfs_readonly = bool.parse(args[++k]); + break; + case "--comment": case "--comments": App.cmd_comments = args[++k]; @@ -368,6 +372,7 @@ public class AppConsole : GLib.Object { msg += " --check " + _("Create snapshot if scheduled") + "\n"; msg += " --create " + _("Create snapshot (even if not scheduled)") + "\n"; msg += " --comments " + _("Set snapshot description") + "\n"; + msg += " --readonly " + _("Create read-only snapshots (BTRFS only) (default: config)") + "\n"; msg += " --tags {O,B,H,D,W,M} " + _("Add tags to snapshot (default: O)") + "\n";; msg += "\n"; msg += _("Restore") + ":\n"; diff --git a/src/Core/Main.vala b/src/Core/Main.vala index fe72628c..950b8fe3 100644 --- a/src/Core/Main.vala +++ b/src/Core/Main.vala @@ -50,6 +50,7 @@ public class Main : GLib.Object{ public string backup_parent_uuid = ""; public bool btrfs_mode = true; + public bool btrfs_readonly = true; public bool include_btrfs_home_for_backup = false; public bool include_btrfs_home_for_restore = false; @@ -1654,7 +1655,7 @@ public class Main : GLib.Object{ dst_path = dst_path.replace("/@home/@home", "/@home"); } - string cmd = "btrfs subvolume snapshot '%s' '%s' \n".printf(src_path, dst_path); + string cmd = "btrfs subvolume snapshot %s '%s' '%s' \n".printf(btrfs_readonly ? "-r" : "", src_path, dst_path); if (LOG_COMMANDS) { log_debug(cmd); } @@ -1683,7 +1684,7 @@ public class Main : GLib.Object{ // write control file var snapshot = Snapshot.write_control_file( snapshot_path, dt_created, sys_uuid, current_distro.full_name(), - initial_tags, cmd_comments, 0, true, false, repo); + initial_tags, btrfs_readonly ? "ReadOnly" : cmd_comments, 0, true, false, repo); // write subvolume info foreach(var subvol in sys_subvolumes.values){ @@ -3207,6 +3208,7 @@ public class Main : GLib.Object{ config.set_string_member("do_first_run", false.to_string()); config.set_string_member("btrfs_mode", btrfs_mode.to_string()); + config.set_string_member("btrfs_readonly", btrfs_readonly.to_string()); config.set_string_member("include_btrfs_home_for_backup", include_btrfs_home_for_backup.to_string()); config.set_string_member("include_btrfs_home_for_restore", include_btrfs_home_for_restore.to_string()); config.set_string_member("stop_cron_emails", stop_cron_emails.to_string()); @@ -3304,6 +3306,8 @@ public class Main : GLib.Object{ bool do_first_run = json_get_bool(config, "do_first_run", false); // false as default btrfs_mode = json_get_bool(config, "btrfs_mode", false); // false as default + + btrfs_readonly = json_get_bool(config, "btrfs_readonly", true); // true as default if (do_first_run){ set_first_run_flag(); diff --git a/src/Gtk/SnapshotBackendBox.vala b/src/Gtk/SnapshotBackendBox.vala index 9df91918..8a1c130b 100644 --- a/src/Gtk/SnapshotBackendBox.vala +++ b/src/Gtk/SnapshotBackendBox.vala @@ -36,6 +36,7 @@ class SnapshotBackendBox : Gtk.Box{ private Gtk.RadioButton opt_rsync; private Gtk.RadioButton opt_btrfs; + private Gtk.CheckButton opt_btrfs_readonly; private Gtk.Label lbl_description; private Gtk.Window parent_window; @@ -103,15 +104,34 @@ class SnapshotBackendBox : Gtk.Box{ } opt_btrfs.toggled.connect(()=>{ + add_opt_btrfs_ro(hbox); if (opt_btrfs.active){ App.btrfs_mode = true; init_backend(); type_changed(); update_description(); } + this.show_all(); }); } + private void add_opt_btrfs_ro(Gtk.Box hbox){ + if (opt_btrfs.active){ + var opt = new Gtk.CheckButton.with_label(_("Create Read-only snapshots by default")); + hbox.add(opt); + opt_btrfs_readonly = opt; + + opt_btrfs_readonly.toggled.connect(()=>{ + App.btrfs_readonly = opt_btrfs_readonly.active; + }); + } else { + if (opt_btrfs_readonly != null){ + hbox.remove(opt_btrfs_readonly); + opt_btrfs_readonly = null; + } + } + } + private bool check_for_btrfs_tools() { try { const string args[] = {"lsblk", "-o", "FSTYPE", null}; @@ -212,6 +232,7 @@ class SnapshotBackendBox : Gtk.Box{ public void refresh(){ opt_btrfs.active = App.btrfs_mode; + opt_btrfs_readonly.active = App.btrfs_readonly; type_changed(); update_description(); }