~teejee2008/timeshift/trunk

« back to all changes in this revision

Viewing changes to src/Main.vala

  • Committer: Tony George
  • Date: 2016-09-18 13:58:57 UTC
  • Revision ID: tony.george.kol@gmail.com-20160918135857-qztjh2kw8mxqfmsf
fstab and crypttab files will be updated correctly on target system when system is restored or cloned

Show diffs side-by-side

added added

removed removed

Lines of Context:
2292
2292
 
2293
2293
                        // skip mounting for non-system devices
2294
2294
                        
2295
 
                        if (mnt.mount_point.has_prefix("/mnt") || mnt.mount_point.has_prefix("/mount")
2296
 
                                || mnt.mount_point.has_prefix("/sdcard") || mnt.mount_point.has_prefix("/cdrom")
2297
 
                                || mnt.mount_point.has_prefix("/media") || (mnt.mount_point == "none")
2298
 
                                || !mnt.mount_point.has_prefix("/")
2299
 
                                || (!mnt.device.has_prefix("/dev/") && !mnt.device.down().has_prefix("uuid="))){
2300
 
                                
 
2295
                        if (!mnt.is_for_system_directory()){
2301
2296
                                continue;
2302
2297
                        }
2303
2298
 
2304
2299
                        // find device by name or uuid
2305
2300
                        
2306
2301
                        Device mnt_dev = null;
2307
 
                        if (mnt.get_uuid().length > 0){
2308
 
                                mnt_dev = Device.get_device_by_uuid(mnt.get_uuid());
 
2302
                        if (mnt.device_uuid.length > 0){
 
2303
                                mnt_dev = Device.get_device_by_uuid(mnt.device_uuid);
2309
2304
                        }
2310
2305
                        else{
2311
2306
                                mnt_dev = Device.get_device_by_name(mnt.device);
2333
2328
 
2334
2329
                                // try again - find device by name or uuid
2335
2330
                        
2336
 
                                if (mnt.get_uuid().length > 0){
2337
 
                                        mnt_dev = Device.get_device_by_uuid(mnt.get_uuid());
 
2331
                                if (mnt.device_uuid.length > 0){
 
2332
                                        mnt_dev = Device.get_device_by_uuid(mnt.device_uuid);
2338
2333
                                }
2339
2334
                                else{
2340
2335
                                        mnt_dev = Device.get_device_by_name(mnt.device);
2642
2637
                foreach(var entry in App.mount_list){
2643
2638
                        if (entry.device == null){ continue; }
2644
2639
                        
2645
 
                        if ((entry.device != null) && (entry.subvolume_name().length > 0)){
 
2640
                        if ((entry.device != null)
 
2641
                                && (entry.device.fstype == "btrfs")
 
2642
                                && (entry.subvolume_name().length > 0)){
 
2643
                                        
2646
2644
                                // subvolumes are used - show subvolume column
2647
2645
                                show_subvolume = true;
2648
2646
                                break;
2993
2991
                        //update /etc/fstab when restoring to another device --------------------
2994
2992
 
2995
2993
                        if (!restore_current_system){
2996
 
                                string fstab_path = target_path + "etc/fstab";
2997
 
                                var fstab_list = FsTabEntry.read_file(fstab_path);
2998
 
 
2999
 
                                foreach(var mount_entry in mount_list){
3000
 
                                        bool found = false;
3001
 
                                        foreach(var fstab_entry in fstab_list){
3002
 
                                                if (fstab_entry.mount_point == mount_entry.mount_point){
3003
 
                                                        found = true;
3004
 
                                                        
3005
 
                                                        //update fstab entry
3006
 
                                                        fstab_entry.device = "UUID=%s".printf(mount_entry.device.uuid);
3007
 
                                                        fstab_entry.type = mount_entry.device.fstype;
3008
 
 
3009
 
                                                        //fix mount options for / and /home
3010
 
                                                        if (restore_target.fstype != "btrfs"){
3011
 
                                                                
3012
 
                                                                if ((fstab_entry.mount_point == "/")
3013
 
                                                                        && fstab_entry.options.contains("subvol=@")){
3014
 
                                                                                
3015
 
                                                                        fstab_entry.options = fstab_entry.options.replace("subvol=@","").strip();
3016
 
                                                                        
3017
 
                                                                        if (fstab_entry.options.has_suffix(",")){
3018
 
                                                                                fstab_entry.options = fstab_entry.options[0:fstab_entry.options.length - 1];
3019
 
                                                                        }
3020
 
                                                                }
3021
 
                                                                else if ((fstab_entry.mount_point == "/home")
3022
 
                                                                        && fstab_entry.options.contains("subvol=@home")){
3023
 
                                                                                
3024
 
                                                                        fstab_entry.options = fstab_entry.options.replace("subvol=@home","").strip();
3025
 
 
3026
 
                                                                        if (fstab_entry.options.has_suffix(",")){
3027
 
                                                                                fstab_entry.options = fstab_entry.options[0:fstab_entry.options.length - 1];
3028
 
                                                                        }
3029
 
                                                                }
3030
 
                                                        }
3031
 
                                                }
3032
 
                                        }
3033
 
 
3034
 
                                        if (!found){
3035
 
                                                //add new fstab entry
3036
 
                                                FsTabEntry fstab_entry = new FsTabEntry();
3037
 
                                                fstab_entry.device = "UUID=%s".printf(mount_entry.device.uuid);
3038
 
                                                fstab_entry.mount_point = mount_entry.mount_point;
3039
 
                                                fstab_entry.type = mount_entry.device.fstype;
3040
 
                                                fstab_list.add(fstab_entry);
3041
 
                                        }
3042
 
                                }
3043
 
 
3044
 
                                /*
3045
 
                                 * If user has not mounted /home, and /home is mounted on another device (according to the fstab file)
3046
 
                                 * then remove the /home mount entry from the fstab.
3047
 
                                 * This is required - otherwise when the user boots the restored system they will continue to see
3048
 
                                 * the existing device as /home and instead of seeing the files restored to /home on the *root* device.
3049
 
                                 * We will do this fix only for /home and leave all other mount points untouched.
3050
 
                                 * */
3051
 
 
3052
 
                                bool found_home_in_fstab = false;
3053
 
                                FsTabEntry fstab_home_entry = null;
3054
 
                                foreach(var fstab_entry in fstab_list){
3055
 
                                        if (fstab_entry.mount_point == "/home"){
3056
 
                                                found_home_in_fstab = true;
3057
 
                                                fstab_home_entry = fstab_entry;
3058
 
                                                break;
3059
 
                                        }
3060
 
                                }
3061
 
 
3062
 
                                bool found_home_in_mount_list = false;
3063
 
                                foreach(MountEntry mount_entry in mount_list){
3064
 
                                        if (mount_entry.mount_point == "/home"){
3065
 
                                                found_home_in_mount_list = true;
3066
 
                                                break;
3067
 
                                        }
3068
 
                                }
3069
 
 
3070
 
                                if (found_home_in_fstab && !found_home_in_mount_list){
3071
 
                                        //remove fstab entry for /home
3072
 
                                        fstab_list.remove(fstab_home_entry);
3073
 
                                }
3074
 
 
3075
 
                                // sort the entries based on mount path
3076
 
                                // this is critical to ensure that base paths are mounted before child paths
3077
 
 
3078
 
                                fstab_list.sort((a, b)=>{
3079
 
                                        return strcmp(a.mount_point, b.mount_point);
3080
 
                                });
3081
 
 
3082
 
                                //write the updated file --------------
3083
 
 
3084
 
                                string text = "# <file system> <mount point> <type> <options> <dump> <pass>\n\n";
3085
 
                                text += FsTabEntry.create_file_text(fstab_list.to_array(), false);
3086
 
                                if (file_exists(fstab_path)){
3087
 
                                        file_delete(fstab_path);
3088
 
                                }
3089
 
                                file_write(fstab_path, text);
3090
 
 
3091
 
                                log_msg(_("Updated /etc/fstab on target device") + ": %s".printf(fstab_path));
3092
 
 
3093
 
                                //create folders for mount points in /etc/fstab to prevent mount errors during boot ---------
3094
 
 
3095
 
                                foreach(var fstab_entry in fstab_list){
3096
 
                                        if (fstab_entry.mount_point.length == 0){ continue; }
3097
 
                                        if (!fstab_entry.mount_point.has_prefix("/")){ continue; }
3098
 
                                        
3099
 
                                        string mount_path = target_path +
3100
 
                                                fstab_entry.mount_point[1:fstab_entry.mount_point.length];
3101
 
                                                
3102
 
                                        if (fstab_entry.is_comment || fstab_entry.is_empty_line
3103
 
                                        || (mount_path.length == 0)){
3104
 
                                                
3105
 
                                                continue;
3106
 
                                        }
3107
 
 
3108
 
                                        if (!dir_exists(mount_path)){
3109
 
                                                
3110
 
                                                log_msg("Created mount point on target device: %s".printf(
3111
 
                                                        fstab_entry.mount_point));
3112
 
                                                        
3113
 
                                                dir_create(mount_path);
3114
 
                                        }
3115
 
                                }
 
2994
                                
 
2995
                                fix_fstab_file(target_path);
 
2996
 
 
2997
                                fix_crypttab_file(target_path);
3116
2998
                        }
3117
2999
 
3118
3000
                        unmount_target_device(false);
3126
3008
                thread_restore_running = false;
3127
3009
        }
3128
3010
 
 
3011
        public void fix_fstab_file(string target_path){
 
3012
                
 
3013
                string fstab_path = target_path + "etc/fstab";
 
3014
                var fstab_list = FsTabEntry.read_file(fstab_path);
 
3015
 
 
3016
                foreach(var mnt in mount_list){
 
3017
                        // find existing
 
3018
                        var entry = FsTabEntry.find_entry_by_mount_point(fstab_list, mnt.mount_point);
 
3019
 
 
3020
                        // add if missing
 
3021
                        if (entry == null){
 
3022
                                entry = new FsTabEntry();
 
3023
                                entry.mount_point = mnt.mount_point;
 
3024
                                fstab_list.add(entry);
 
3025
                        }
 
3026
 
 
3027
                        //update fstab entry
 
3028
                        entry.device = "UUID=%s".printf(mnt.device.uuid);
 
3029
                        entry.type = mnt.device.fstype;
 
3030
 
 
3031
                        // fix mount options for non-btrfs device
 
3032
                        if (mnt.device.fstype != "btrfs"){
 
3033
                                // remove subvol option
 
3034
                                entry.remove_option("subvol=%s".printf(entry.subvolume_name()));
 
3035
                        }
 
3036
                }
 
3037
 
 
3038
                /*
 
3039
                 * Remove fstab entries for any system directories that
 
3040
                 * the user has not explicitly mapped before restore/clone
 
3041
                 * This ensures that the cloned/restored system does not mount
 
3042
                 * any devices to system paths that the user has not explicitly specified
 
3043
                 * */
 
3044
 
 
3045
                for(int i = fstab_list.size - 1; i >= 0; i--){
 
3046
                        var entry = fstab_list[i];
 
3047
                        
 
3048
                        if (!entry.is_for_system_directory()){ continue; }
 
3049
                        
 
3050
                        var mnt = MountEntry.find_entry_by_mount_point(mount_list, entry.mount_point);
 
3051
                        if (mnt == null){
 
3052
                                fstab_list.remove(entry);
 
3053
                        }
 
3054
                }
 
3055
                
 
3056
                // write the updated file
 
3057
 
 
3058
                FsTabEntry.write_file(fstab_list, fstab_path, false);
 
3059
 
 
3060
                log_msg(_("Updated /etc/fstab on target device") + ": %s".printf(fstab_path));
 
3061
 
 
3062
                // create directories on disk for mount points in /etc/fstab
 
3063
 
 
3064
                foreach(var entry in fstab_list){
 
3065
                        if (entry.mount_point.length == 0){ continue; }
 
3066
                        if (!entry.mount_point.has_prefix("/")){ continue; }
 
3067
                        
 
3068
                        string mount_path = path_combine(
 
3069
                                target_path, entry.mount_point);
 
3070
                                
 
3071
                        if (entry.is_comment
 
3072
                                || entry.is_empty_line
 
3073
                                || (mount_path.length == 0)){
 
3074
                                
 
3075
                                continue;
 
3076
                        }
 
3077
 
 
3078
                        if (!dir_exists(mount_path)){
 
3079
                                
 
3080
                                log_msg("Created mount point on target device: %s".printf(
 
3081
                                        entry.mount_point));
 
3082
                                        
 
3083
                                dir_create(mount_path);
 
3084
                        }
 
3085
                }
 
3086
        }
 
3087
 
 
3088
        public void fix_crypttab_file(string target_path){
 
3089
                string file_path = target_path + "etc/crypttab";
 
3090
                var crypttab_list = CryptTabEntry.read_file(file_path);
 
3091
 
 
3092
                // add option "nofail" to existing entries
 
3093
                
 
3094
                foreach(var entry in crypttab_list){
 
3095
                        entry.append_option("nofail");
 
3096
                }
 
3097
 
 
3098
                // check and add entries for mapped devices which are encrypted
 
3099
                
 
3100
                foreach(var mnt in mount_list){
 
3101
                        if ((mnt.device != null) && (mnt.device.is_on_encrypted_partition())){
 
3102
                                
 
3103
                                // find existing
 
3104
                                var entry = CryptTabEntry.find_entry_by_uuid(
 
3105
                                        crypttab_list, mnt.device.parent.uuid);
 
3106
 
 
3107
                                // add if missing
 
3108
                                if (entry == null){
 
3109
                                        entry = new CryptTabEntry();
 
3110
                                        crypttab_list.add(entry);
 
3111
                                }
 
3112
                                
 
3113
                                // set custom values
 
3114
                                entry.device_uuid = mnt.device.parent.uuid;
 
3115
                                entry.mapped_name = "luks-%s".printf(mnt.device.parent.uuid);
 
3116
                                entry.keyfile = "none";
 
3117
                                entry.options = "luks,nofail";
 
3118
                        }
 
3119
                }
 
3120
 
 
3121
                CryptTabEntry.write_file(crypttab_list, file_path, false);
 
3122
        }
 
3123
 
3129
3124
        public void save_exclude_list_for_restore(string file_path){
3130
3125
 
3131
3126
                try{