Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 72 additions & 42 deletions src/Core/Main.vala
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ public class Main : GLib.Object{
public bool include_btrfs_home_for_backup = false;
public bool include_btrfs_home_for_restore = false;
public static bool btrfs_version__can_recursive_delete = false;

public string root_subvolume_name = "@";
public string home_subvolume_name = "@home";

public bool stop_cron_emails = true;

Expand Down Expand Up @@ -289,6 +292,23 @@ public class Main : GLib.Object{
this.app_conf_path_old = "/etc/timeshift.json";
this.app_conf_path_default = GLib.Path.build_path (GLib.Path.DIR_SEPARATOR_S, Constants.SYSCONFDIR, "timeshift", "default.json");
//sys_root and sys_home will be initialized by update_partition_list()

// Detect subvolume names based on distro id.
// Only has effect when timeshift is opened the first time,
// otherwise the setting is overwritten by loading the config.
if (this.current_distro.dist_id.down() == "fedora") {
this.root_subvolume_name = "root";
this.home_subvolume_name = "home";
}
else if (this.current_distro.dist_id.down() == "debian") {
this.root_subvolume_name = "@rootfs";
this.home_subvolume_name = "";
this.include_btrfs_home_for_backup = false;
}
else { //if (this.current_distro.dist_id.down() == "ubuntu")
this.root_subvolume_name = "@";
this.home_subvolume_name = "@home";
}

// check if running locally ------------------------

Expand Down Expand Up @@ -488,9 +508,9 @@ public class Main : GLib.Object{

log_debug("check_btrfs_layout_system()");

bool supported = sys_subvolumes.has_key("@");
bool supported = sys_subvolumes.has_key(root_subvolume_name);
if (include_btrfs_home_for_backup){
supported = supported && sys_subvolumes.has_key("@home");
supported = supported && sys_subvolumes.has_key(home_subvolume_name);
}

if (!supported){
Expand Down Expand Up @@ -521,18 +541,18 @@ public class Main : GLib.Object{

if (dev_home != dev_root){

supported = supported && check_btrfs_volume(dev_root, "@", unlock);
supported = supported && check_btrfs_volume(dev_root, root_subvolume_name, unlock);

if (include_btrfs_home_for_backup){
supported = supported && check_btrfs_volume(dev_home, "@home", unlock);
supported = supported && check_btrfs_volume(dev_home, home_subvolume_name, unlock);
}
}
else{
if (include_btrfs_home_for_backup){
supported = supported && check_btrfs_volume(dev_root, "@,@home", unlock);
}
else{
supported = supported && check_btrfs_volume(dev_root, "@", unlock);
supported = supported && check_btrfs_volume(dev_root, root_subvolume_name, unlock);
}
}
}
Expand Down Expand Up @@ -1720,9 +1740,9 @@ public class Main : GLib.Object{

log_msg(_("Creating new backup...") + "(BTRFS)");

log_msg(_("Saving to device") + ": %s".printf(repo.device.device) + ", " + _("mounted at path") + ": %s".printf(repo.mount_paths["@"]));
log_msg(_("Saving to device") + ": %s".printf(repo.device.device) + ", " + _("mounted at path") + ": %s".printf(repo.mount_paths[root_subvolume_name]));
if ((repo.device_home != null) && (repo.device_home.uuid != repo.device.uuid)){
log_msg(_("Saving to device") + ": %s".printf(repo.device_home.device) + ", " + _("mounted at path") + ": %s".printf(repo.mount_paths["@home"]));
log_msg(_("Saving to device") + ": %s".printf(repo.device_home.device) + ", " + _("mounted at path") + ": %s".printf(repo.mount_paths[home_subvolume_name]));
}

// take new backup ---------------------------------
Expand All @@ -1739,11 +1759,11 @@ public class Main : GLib.Object{

// create subvolume snapshots

var subvol_names = new string[] { "@" };
var subvol_names = new string[] { root_subvolume_name };

if (include_btrfs_home_for_backup){

subvol_names = new string[] { "@","@home" };
subvol_names = new string[] { root_subvolume_name,home_subvolume_name };
}

foreach(var subvol_name in subvol_names){
Expand Down Expand Up @@ -1786,7 +1806,7 @@ public class Main : GLib.Object{

//log_msg(_("Writing control file..."));

snapshot_path = path_combine(repo.mount_paths["@"], "timeshift-btrfs/snapshots/%s".printf(snapshot_name));
snapshot_path = path_combine(repo.mount_paths[root_subvolume_name], "timeshift-btrfs/snapshots/%s".printf(snapshot_name));

string initial_tags = (tag == "ondemand") ? "" : tag;

Expand Down Expand Up @@ -2344,11 +2364,11 @@ public class Main : GLib.Object{
// final check - check if target root device is mounted

if (btrfs_mode){
if (repo.mount_paths["@"].length == 0){
if (repo.mount_paths[root_subvolume_name].length == 0){
log_error(_("BTRFS device is not mounted") + ": @");
return false;
}
if (include_btrfs_home_for_restore && (repo.mount_paths["@home"].length == 0)){
if (include_btrfs_home_for_restore && (repo.mount_paths[home_subvolume_name].length == 0)){
log_error(_("BTRFS device is not mounted") + ": @home");
return false;
}
Expand Down Expand Up @@ -2430,7 +2450,7 @@ public class Main : GLib.Object{

if (!App.snapshot_to_restore.subvolumes.has_key(entry.subvolume_name())){ continue; }

if ((entry.subvolume_name() == "@home") && !include_btrfs_home_for_restore){ continue; }
if ((entry.subvolume_name() == home_subvolume_name) && !include_btrfs_home_for_restore){ continue; }
}

string dev_name = entry.device.full_name_with_parent;
Expand Down Expand Up @@ -2466,7 +2486,7 @@ public class Main : GLib.Object{

if (!App.snapshot_to_restore.subvolumes.has_key(entry.subvolume_name())){ continue; }

if ((entry.subvolume_name() == "@home") && !include_btrfs_home_for_restore){ continue; }
if ((entry.subvolume_name() == home_subvolume_name) && !include_btrfs_home_for_restore){ continue; }
}

string dev_name = entry.device.full_name_with_parent;
Expand Down Expand Up @@ -3166,7 +3186,7 @@ public class Main : GLib.Object{

foreach(var subvol in snapshot_to_restore.subvolumes.values){

if ((subvol.name == "@home") && !include_btrfs_home_for_restore){ continue; }
if ((subvol.name == home_subvolume_name) && !include_btrfs_home_for_restore){ continue; }

subvol.restore();
}
Expand Down Expand Up @@ -3230,12 +3250,12 @@ public class Main : GLib.Object{

if (found){
//delete system subvolumes
if (sys_subvolumes.has_key("@") && snapshot_to_restore.subvolumes.has_key("@")){
sys_subvolumes["@"].remove();
if (sys_subvolumes.has_key(root_subvolume_name) && snapshot_to_restore.subvolumes.has_key(root_subvolume_name)){
sys_subvolumes[root_subvolume_name].remove();
log_msg(_("Deleted subvolume") + ": @");
}
if (include_btrfs_home_for_restore && sys_subvolumes.has_key("@home") && snapshot_to_restore.subvolumes.has_key("@home")){
sys_subvolumes["@home"].remove();
if (include_btrfs_home_for_restore && sys_subvolumes.has_key(home_subvolume_name) && snapshot_to_restore.subvolumes.has_key(home_subvolume_name)){
sys_subvolumes[home_subvolume_name].remove();
log_msg(_("Deleted subvolume") + ": @home");
}

Expand Down Expand Up @@ -3263,9 +3283,9 @@ public class Main : GLib.Object{

var subvol_list = new Gee.ArrayList<Subvolume>();

var subvol_names = new string[] { "@" };
var subvol_names = new string[] { root_subvolume_name };
if (include_btrfs_home_for_restore){
subvol_names = new string[] { "@","@home" };
subvol_names = new string[] { root_subvolume_name,home_subvolume_name };
}

foreach(string subvol_name in subvol_names){
Expand Down Expand Up @@ -3294,7 +3314,7 @@ public class Main : GLib.Object{
return false;
}
else{
var subvol_dev = (subvol_name == "@") ? repo.device : repo.device_home;
var subvol_dev = (subvol_name == root_subvolume_name) ? repo.device : repo.device_home;
subvol_list.add(new Subvolume(subvol_name, dst_path, subvol_dev.uuid, repo));

log_msg(_("Moved system subvolume to snapshot directory") + ": %s".printf(subvol_name));
Expand All @@ -3308,11 +3328,11 @@ public class Main : GLib.Object{
else{
// write control file -----------

snapshot_path = path_combine(repo.mount_paths["@"], "timeshift-btrfs/snapshots/%s".printf(snapshot_name));
snapshot_path = path_combine(repo.mount_paths[root_subvolume_name], "timeshift-btrfs/snapshots/%s".printf(snapshot_name));

var snap = Snapshot.write_control_file(
snapshot_path, dt_created, repo.device.uuid,
LinuxDistro.get_dist_info(path_combine(snapshot_path,"@")).full_name(),
LinuxDistro.get_dist_info(path_combine(snapshot_path,root_subvolume_name)).full_name(),
"ondemand", "", 0, true, false, repo);

snap.description = "Before restoring '%s'".printf(snapshot_to_restore.date_formatted);
Expand Down Expand Up @@ -3357,6 +3377,9 @@ public class Main : GLib.Object{
config.set_string_member("parent_device_uuid", backup_parent_uuid);
}

config.set_string_member("root_subvolume_name", root_subvolume_name);
config.set_string_member("home_subvolume_name", home_subvolume_name);

config.set_string_member("do_first_run", false.to_string());
config.set_string_member("btrfs_mode", btrfs_mode.to_string());
config.set_string_member("include_btrfs_home_for_backup", include_btrfs_home_for_backup.to_string());
Expand Down Expand Up @@ -3476,6 +3499,9 @@ public class Main : GLib.Object{
if (cmd_btrfs_mode != null){
btrfs_mode = cmd_btrfs_mode; //override
}

root_subvolume_name = json_get_string(config,"root_subvolume_name", root_subvolume_name);
home_subvolume_name = json_get_string(config,"home_subvolume_name", home_subvolume_name);

backup_uuid = json_get_string(config,"backup_device_uuid", backup_uuid);
backup_parent_uuid = json_get_string(config,"parent_device_uuid", backup_parent_uuid);
Expand Down Expand Up @@ -3544,7 +3570,7 @@ public class Main : GLib.Object{

// load some defaults for first-run based on user's system type

bool supported = sys_subvolumes.has_key("@") && cmd_exists("btrfs"); // && sys_subvolumes.has_key("@home")
bool supported = sys_subvolumes.has_key(root_subvolume_name) && cmd_exists("btrfs"); // && sys_subvolumes.has_key(home_subvolume_name)
if (supported || (cmd_btrfs_mode == true)){
log_msg(_("Selected default snapshot type") + ": %s".printf("BTRFS"));
btrfs_mode = true;
Expand Down Expand Up @@ -3959,8 +3985,8 @@ public class Main : GLib.Object{
update_partitions();

// In BTRFS mode, select the system disk if system disk is BTRFS
if (btrfs_mode && sys_subvolumes.has_key("@")){
var subvol_root = sys_subvolumes["@"];
if (btrfs_mode && sys_subvolumes.has_key(root_subvolume_name)){
var subvol_root = sys_subvolumes[root_subvolume_name];
repo = new SnapshotRepo.from_device(subvol_root.get_device(), parent_win, btrfs_mode);
return;
}
Expand All @@ -3983,7 +4009,7 @@ public class Main : GLib.Object{
if (dev.has_children()) { return false; }

if (btrfs_mode && ((dev.fstype == "btrfs")||(dev.fstype == "luks"))){
if (check_btrfs_volume(dev, "@", unlock)){
if (check_btrfs_volume(dev, root_subvolume_name, unlock)){
return true;
}
}
Expand Down Expand Up @@ -4109,16 +4135,20 @@ public class Main : GLib.Object{
}

public bool query_subvolume_ids(){
bool ok = query_subvolume_id("@");
bool ok = query_subvolume_id(root_subvolume_name);
if ((repo.device_home != null) && (repo.device.uuid != repo.device_home.uuid)){
ok = ok && query_subvolume_id("@home");
ok = ok && query_subvolume_id(home_subvolume_name);
}
return ok;
}

public bool query_subvolume_id(string subvol_name){

log_debug("query_subvolume_id():%s".printf(subvol_name));

// Early out when configured subvolume name != actual.
if(sys_subvolumes[root_subvolume_name] == null || sys_subvolumes[home_subvolume_name] == null)
return false;

string cmd = "";
string std_out;
Expand Down Expand Up @@ -4149,14 +4179,14 @@ public class Main : GLib.Object{

Subvolume subvol = null;

if ((sys_subvolumes.size > 0) && line.has_suffix(sys_subvolumes["@"].path.replace(repo.mount_paths["@"] + "/"," "))){
subvol = sys_subvolumes["@"];
if ((sys_subvolumes.size > 0) && line.has_suffix(sys_subvolumes[root_subvolume_name].path.replace(repo.mount_paths[root_subvolume_name] + "/"," "))){
subvol = sys_subvolumes[root_subvolume_name];
}
else if ((sys_subvolumes.size > 0)
&& sys_subvolumes.has_key("@home")
&& line.has_suffix(sys_subvolumes["@home"].path.replace(repo.mount_paths["@home"] + "/"," "))){
&& sys_subvolumes.has_key(home_subvolume_name)
&& line.has_suffix(sys_subvolumes[home_subvolume_name].path.replace(repo.mount_paths[home_subvolume_name] + "/"," "))){

subvol = sys_subvolumes["@home"];
subvol = sys_subvolumes[home_subvolume_name];
}
else {
foreach(var bak in repo.snapshots){
Expand All @@ -4178,9 +4208,9 @@ public class Main : GLib.Object{
}

public bool query_subvolume_quotas(){
bool ok = query_subvolume_quota("@");
bool ok = query_subvolume_quota(root_subvolume_name);
if (repo.device.uuid != repo.device_home.uuid){
ok = ok && query_subvolume_quota("@home");
ok = ok && query_subvolume_quota(home_subvolume_name);
}
return ok;
}
Expand Down Expand Up @@ -4241,15 +4271,15 @@ public class Main : GLib.Object{

Subvolume subvol = null;

if ((sys_subvolumes.size > 0) && (sys_subvolumes["@"].id == subvol_id)){
if ((sys_subvolumes.size > 0) && (sys_subvolumes[root_subvolume_name].id == subvol_id)){

subvol = sys_subvolumes["@"];
subvol = sys_subvolumes[root_subvolume_name];
}
else if ((sys_subvolumes.size > 0)
&& sys_subvolumes.has_key("@home")
&& (sys_subvolumes["@home"].id == subvol_id)){
&& sys_subvolumes.has_key(home_subvolume_name)
&& (sys_subvolumes[home_subvolume_name].id == subvol_id)){

subvol = sys_subvolumes["@home"];
subvol = sys_subvolumes[home_subvolume_name];
}
else {
foreach(var bak in repo.snapshots){
Expand Down
4 changes: 2 additions & 2 deletions src/Core/Snapshot.vala
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ public class Snapshot : GLib.Object{
live = json_get_bool(config,"live",false);
string type = config.get_string_member_with_default("type", "rsync");

string extension = (type == "btrfs") ? "@" : "localhost";
string extension = (type == "btrfs") ? App.root_subvolume_name : "localhost";
distro = LinuxDistro.get_dist_info(path_combine(path, extension));

//log_debug("repo.mount_path: %s".printf(repo.mount_path));
Expand All @@ -239,7 +239,7 @@ public class Snapshot : GLib.Object{

foreach(string subvol_name in subvols.get_members()){

if ((subvol_name != "@")&&(subvol_name != "@home")){ continue; }
if ((subvol_name != App.root_subvolume_name)&&(subvol_name != App.home_subvolume_name)){ continue; }

paths[subvol_name] = path.replace(repo.mount_path, repo.mount_paths[subvol_name]);

Expand Down
20 changes: 10 additions & 10 deletions src/Core/SnapshotRepo.vala
Original file line number Diff line number Diff line change
Expand Up @@ -193,31 +193,31 @@ public class SnapshotRepo : GLib.Object{
}

// rsync
mount_paths["@"] = "";
mount_paths["@home"] = "";
mount_paths[App.root_subvolume_name] = "";
mount_paths[App.home_subvolume_name] = "";

if (btrfs_mode){

mount_paths["@"] = mount_path;
mount_paths["@home"] = mount_path; //default
mount_paths[App.root_subvolume_name] = mount_path;
mount_paths[App.home_subvolume_name] = mount_path; //default
device_home = device; //default

// mount @home if on different disk -------

var repo_subvolumes = Subvolume.detect_subvolumes_for_system_by_path(path_combine(mount_path,"@"), this, parent_window);
var repo_subvolumes = Subvolume.detect_subvolumes_for_system_by_path(path_combine(mount_path,App.root_subvolume_name), this, parent_window);

if (repo_subvolumes.has_key("@home")){
if (repo_subvolumes.has_key(App.home_subvolume_name)){

var subvol = repo_subvolumes["@home"];
var subvol = repo_subvolumes[App.home_subvolume_name];

if (subvol.device_uuid != device.uuid){

// @home is on a separate device
device_home = subvol.get_device();

mount_paths["@home"] = unlock_and_mount_device(device_home, App.mount_point_app + "/backup-home");
mount_paths[App.home_subvolume_name] = unlock_and_mount_device(device_home, App.mount_point_app + "/backup-home");

if (mount_paths["@home"].length == 0){
if (mount_paths[App.home_subvolume_name].length == 0){
return false;
}
}
Expand Down Expand Up @@ -505,7 +505,7 @@ public class SnapshotRepo : GLib.Object{

log_debug("SnapshotRepo: has_btrfs_system()");

var root_path = path_combine(mount_paths["@"],"@");
var root_path = path_combine(mount_paths[App.root_subvolume_name],App.root_subvolume_name);
log_debug("root_path=%s".printf(root_path));
log_debug("btrfs_mode=%s".printf(btrfs_mode.to_string()));
if (btrfs_mode){
Expand Down
Loading