diff options
| author | David Lönnhager <david.l@mullvad.net> | 2020-08-12 12:55:32 +0200 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2020-08-13 13:34:43 +0200 |
| commit | 14b0a39e02ded2e9e8e5a51a4f49cb943d32a8b9 (patch) | |
| tree | 83267bb409434adb3f913b1da4ccfe1801720b2f | |
| parent | 3ba3cce571514d5bdb877915d4f171b1904fa152 (diff) | |
| download | mullvadvpn-14b0a39e02ded2e9e8e5a51a4f49cb943d32a8b9.tar.xz mullvadvpn-14b0a39e02ded2e9e8e5a51a4f49cb943d32a8b9.zip | |
Improve error handling for settings migration
| -rw-r--r-- | mullvad-daemon/src/settings.rs | 102 |
1 files changed, 60 insertions, 42 deletions
diff --git a/mullvad-daemon/src/settings.rs b/mullvad-daemon/src/settings.rs index 96b83626f1..c343d7c336 100644 --- a/mullvad-daemon/src/settings.rs +++ b/mullvad-daemon/src/settings.rs @@ -78,21 +78,38 @@ impl SettingsPersister { } fn load_settings(path: &Path) -> (Settings, bool) { - Self::load_settings_from_file(path) - .or_else(|error| match error { - #[cfg(windows)] - LoadSettingsError::FileNotFound => { - Self::try_load_settings_after_windows_update(path) - } - _ => Err(error), - }) - .unwrap_or_else(|error| { - info!( - "{}", - error.display_chain_with_msg("Failed to load settings. Using defaults.") - ); - (Settings::default(), true) - }) + let error = match Self::load_settings_from_file(path) { + Ok(value) => return value, + Err(error) => error, + }; + + #[cfg(windows)] + let error = if let LoadSettingsError::FileNotFound = error { + info!( + "No settings file found. Attempting migration from Windows update backup location" + ); + match windows::migrate_after_windows_update() { + Ok(Some(())) => match Self::load_settings_from_file(path) { + Ok(value) => return value, + Err(error) => error, + }, + Ok(None) => LoadSettingsError::FileNotFound, + Err(error) => LoadSettingsError::WinMigrationError(error), + } + } else { + error + }; + + if let LoadSettingsError::FileNotFound = error { + info!("No settings were found. Using defaults."); + } else { + info!( + "{}", + error.display_chain_with_msg("Failed to load settings. Using defaults.") + ); + } + + (Settings::default(), true) } fn load_settings_from_file(path: &Path) -> Result<(Settings, bool), LoadSettingsError> { @@ -114,16 +131,6 @@ impl SettingsPersister { .map_err(LoadSettingsError::ParseError) } - #[cfg(windows)] - fn try_load_settings_after_windows_update( - path: &Path, - ) -> Result<(Settings, bool), LoadSettingsError> { - info!("No settings file found. Attempting migration from Windows update backup location"); - - windows::migrate_after_windows_update().map_err(LoadSettingsError::WinMigrationError)?; - Self::load_settings_from_file(path) - } - /// Serializes the settings and saves them to the file it was loaded from. fn save(&mut self) -> Result<(), Error> { debug!("Writing settings to {}", self.path.display()); @@ -287,18 +294,12 @@ mod windows { #[derive(err_derive::Error, Debug)] #[error(no_from)] pub enum Error { - #[error(display = "No files to migrate")] - NothingToMigrate, - #[error(display = "Unable to find settings directory")] FindSettings(#[error(source)] mullvad_paths::Error), #[error(display = "Unable to find local appdata directory")] FindAppData, - #[error(display = "Migration was aborted to avoid overwriting current settings")] - SettingsExist, - #[error(display = "Could not acquire security descriptor of backup directory")] SecurityInformation(#[error(source)] io::Error), @@ -309,25 +310,40 @@ mod windows { IoError(#[error(source)] io::Error), } - pub fn migrate_after_windows_update() -> Result<(), Error> { + /// Attempts to restore the Mullvad settings from `C:\windows.old` after an update of Windows. + /// Upon success, it returns `Ok(Some(()))` if the migration succeeded, and `Ok(None)` if no + /// migration was needed. + pub fn migrate_after_windows_update() -> Result<Option<()>, Error> { let destination_settings_dir = mullvad_paths::settings_dir().map_err(Error::FindSettings)?; let system_appdata_dir = dirs::data_local_dir().ok_or(Error::FindAppData)?; if !destination_settings_dir.starts_with(system_appdata_dir) { - return Err(Error::NothingToMigrate); + return Ok(None); } let settings_path = destination_settings_dir.join(super::SETTINGS_FILE); if settings_path.exists() { - return Err(Error::SettingsExist); + return Ok(None); } let mut components = destination_settings_dir.components(); - let prefix = components.next().ok_or(Error::NothingToMigrate)?; - let root = components.next().ok_or(Error::NothingToMigrate)?; + let prefix = if let Some(prefix) = components.next() { + prefix + } else { + return Ok(None); + }; + let root = if let Some(root) = components.next() { + root + } else { + return Ok(None); + }; let windows_old_dir = Path::new(&prefix).join(&root).join(MIGRATION_DIRNAME); + let source_settings_dir = Path::new(&windows_old_dir).join(&components); + if !source_settings_dir.exists() { + return Ok(None); + } let security_info = SecurityInformation::from_file(windows_old_dir.as_path(), OWNER_SECURITY_INFORMATION) @@ -341,16 +357,11 @@ mod windows { return Err(Error::WrongOwner); } - let source_settings_dir = Path::new(&windows_old_dir).join(&components); - if !source_settings_dir.exists() { - return Err(Error::NothingToMigrate); - } - if !destination_settings_dir.exists() { fs::create_dir_all(&destination_settings_dir).map_err(Error::IoError)?; } - let mut result = Ok(()); + let mut result = Ok(Some(())); for (file, required) in &MIGRATE_FILES { let from = source_settings_dir.join(file); @@ -378,6 +389,13 @@ mod windows { } } + if let Err(error) = fs::remove_dir(source_settings_dir) { + log::trace!( + "{}", + error.display_chain_with_msg("Failed to delete backup directory") + ); + } + result } |
