diff options
| author | David Lönnhager <david.l@mullvad.net> | 2022-05-06 11:48:54 +0200 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2022-05-09 14:56:31 +0200 |
| commit | ecd916b3d2663ccaa4bfb3c7aeb33e11efaebdef (patch) | |
| tree | c6d9f60f9f779f375d6465052637b18b9bde85b1 | |
| parent | 3d62b802f449ddae32c78d8922d3b4aaea3c84a9 (diff) | |
| download | mullvadvpn-ecd916b3d2663ccaa4bfb3c7aeb33e11efaebdef.tar.xz mullvadvpn-ecd916b3d2663ccaa4bfb3c7aeb33e11efaebdef.zip | |
Move directory cleanup to cleanup module
| -rw-r--r-- | mullvad-daemon/src/cleanup.rs | 83 | ||||
| -rw-r--r-- | mullvad-daemon/src/lib.rs | 114 |
2 files changed, 96 insertions, 101 deletions
diff --git a/mullvad-daemon/src/cleanup.rs b/mullvad-daemon/src/cleanup.rs new file mode 100644 index 0000000000..b4765761e0 --- /dev/null +++ b/mullvad-daemon/src/cleanup.rs @@ -0,0 +1,83 @@ +#![cfg(not(target_os = "android"))] + +use std::path::Path; +use tokio::{fs, io}; + +#[derive(err_derive::Error, Debug)] +#[error(no_from)] +pub enum Error { + #[error(display = "Failed to get path")] + PathError(#[error(source)] mullvad_paths::Error), + + #[error(display = "Failed to remove directory {}", _0)] + RemoveDirError(String, #[error(source)] io::Error), + + #[cfg(not(target_os = "windows"))] + #[error(display = "Failed to create directory {}", _0)] + CreateDirError(String, #[error(source)] io::Error), + + #[cfg(target_os = "windows")] + #[error(display = "Failed to get file type info")] + FileTypeError(#[error(source)] io::Error), + + #[cfg(target_os = "windows")] + #[error(display = "Failed to get dir entry")] + FileEntryError(#[error(source)] io::Error), + + #[cfg(target_os = "windows")] + #[error(display = "Failed to read dir entries")] + ReadDirError(#[error(source)] io::Error), +} + +pub async fn clear_directories() -> Result<(), Error> { + clear_log_directory().await?; + clear_cache_directory().await +} + +async fn clear_log_directory() -> Result<(), Error> { + let log_dir = mullvad_paths::get_log_dir().map_err(Error::PathError)?; + clear_directory(&log_dir).await +} + +async fn clear_cache_directory() -> Result<(), Error> { + let cache_dir = mullvad_paths::cache_dir().map_err(Error::PathError)?; + clear_directory(&cache_dir).await +} + +async fn clear_directory(path: &Path) -> Result<(), Error> { + #[cfg(not(target_os = "windows"))] + { + fs::remove_dir_all(path) + .await + .map_err(|e| Error::RemoveDirError(path.display().to_string(), e))?; + fs::create_dir_all(path) + .await + .map_err(|e| Error::CreateDirError(path.display().to_string(), e)) + } + #[cfg(target_os = "windows")] + { + let mut dir = fs::read_dir(&path).await.map_err(Error::ReadDirError)?; + + let mut result = Ok(()); + + while let Some(entry) = dir.next_entry().await.map_err(Error::FileEntryError)? { + let entry_type = match entry.file_type().await { + Ok(entry_type) => entry_type, + Err(error) => { + result = result.and(Err(Error::FileTypeError(error))); + continue; + } + }; + + let removal = if entry_type.is_file() || entry_type.is_symlink() { + fs::remove_file(entry.path()).await + } else { + fs::remove_dir_all(entry.path()).await + }; + result = result.and( + removal.map_err(|e| Error::RemoveDirError(entry.path().display().to_string(), e)), + ); + } + result + } +} diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs index 0a063613e2..302a0f8f57 100644 --- a/mullvad-daemon/src/lib.rs +++ b/mullvad-daemon/src/lib.rs @@ -6,6 +6,8 @@ extern crate serde; pub mod account_history; mod api; +#[cfg(not(target_os = "android"))] +mod cleanup; pub mod device; mod dns; pub mod exception_logging; @@ -51,8 +53,6 @@ use mullvad_types::{ use settings::SettingsPersister; #[cfg(target_os = "android")] use std::os::unix::io::RawFd; -#[cfg(not(target_os = "android"))] -use std::path::Path; #[cfg(target_os = "windows")] use std::{collections::HashSet, ffi::OsString}; use std::{ @@ -76,7 +76,7 @@ use talpid_types::{ tunnel::{ErrorStateCause, TunnelStateTransition}, ErrorExt, }; -#[cfg(not(target_os = "android"))] +#[cfg(any(target_os = "macos", target_os = "linux"))] use tokio::fs; use tokio::io; @@ -150,42 +150,13 @@ pub enum Error { #[error(display = "Account history error")] AccountHistory(#[error(source)] account_history::Error), - #[error(display = "Failed to clear cache directory")] - ClearCacheError, - - #[error(display = "Failed to clear logs directory")] - ClearLogsError, - - #[error(display = "Failed to clear account history")] - ClearAccountHistoryError(#[error(source)] account_history::Error), - - #[error(display = "Failed to clear settings")] - ClearSettingsError(#[error(source)] settings::Error), + #[cfg(not(target_os = "android"))] + #[error(display = "Factory reset partially failed: {}", _0)] + FactoryResetError(&'static str), #[error(display = "Tunnel state machine error")] TunnelError(#[error(source)] tunnel_state_machine::Error), - #[error(display = "Failed to remove directory {}", _0)] - RemoveDirError(String, #[error(source)] io::Error), - - #[error(display = "Failed to create directory {}", _0)] - CreateDirError(String, #[error(source)] io::Error), - - #[error(display = "Failed to get path")] - PathError(#[error(source)] mullvad_paths::Error), - - #[cfg(target_os = "windows")] - #[error(display = "Failed to get file type info")] - FileTypeError(#[error(source)] io::Error), - - #[cfg(target_os = "windows")] - #[error(display = "Failed to get dir entry")] - FileEntryError(#[error(source)] io::Error), - - #[cfg(target_os = "windows")] - #[error(display = "Failed to read dir entries")] - ReadDirError(#[error(source)] io::Error), - #[cfg(target_os = "macos")] #[error(display = "Failed to set exclusion group")] GroupIdError(#[error(source)] io::Error), @@ -1515,7 +1486,6 @@ where "{}", error.display_chain_with_msg("Failed to clear device cache") ); - last_error = Err(Error::LogoutError(error)); } if let Err(error) = self.account_history.clear().await { @@ -1523,32 +1493,26 @@ where "{}", error.display_chain_with_msg("Failed to clear account history") ); - last_error = Err(Error::ClearAccountHistoryError(error)); + last_error = Err(Error::FactoryResetError("Failed to clear account history")); } if let Err(e) = self.settings.reset().await { log::error!("Failed to reset settings: {}", e); - last_error = Err(Error::ClearSettingsError(e)); + last_error = Err(Error::FactoryResetError("Failed to reset settings")); } // Shut the daemon down. self.trigger_shutdown_event(); self.shutdown_tasks.push(Box::pin(async move { - if let Err(e) = Self::clear_cache_directory().await { + if let Err(e) = cleanup::clear_directories().await { log::error!( "{}", - e.display_chain_with_msg("Failed to clear cache directory") + e.display_chain_with_msg("Failed to clear cache and log directories") ); - last_error = Err(Error::ClearCacheError); - } - - if let Err(e) = Self::clear_log_directory().await { - log::error!( - "{}", - e.display_chain_with_msg("Failed to clear log directory") - ); - last_error = Err(Error::ClearLogsError); + last_error = Err(Error::FactoryResetError( + "Failed to clear cache and log directories", + )); } Self::oneshot_send(tx, last_error, "factory_reset response"); })); @@ -2251,58 +2215,6 @@ where .expect("Tunnel state machine has stopped"); } - #[cfg(not(target_os = "android"))] - async fn clear_log_directory() -> Result<(), Error> { - let log_dir = mullvad_paths::get_log_dir().map_err(Error::PathError)?; - Self::clear_directory(&log_dir).await - } - - #[cfg(not(target_os = "android"))] - async fn clear_cache_directory() -> Result<(), Error> { - let cache_dir = mullvad_paths::cache_dir().map_err(Error::PathError)?; - Self::clear_directory(&cache_dir).await - } - - #[cfg(not(target_os = "android"))] - async fn clear_directory(path: &Path) -> Result<(), Error> { - #[cfg(not(target_os = "windows"))] - { - fs::remove_dir_all(path) - .await - .map_err(|e| Error::RemoveDirError(path.display().to_string(), e))?; - fs::create_dir_all(path) - .await - .map_err(|e| Error::CreateDirError(path.display().to_string(), e)) - } - #[cfg(target_os = "windows")] - { - let mut dir = fs::read_dir(&path).await.map_err(Error::ReadDirError)?; - - let mut result = Ok(()); - - while let Some(entry) = dir.next_entry().await.map_err(Error::FileEntryError)? { - let entry_type = match entry.file_type().await { - Ok(entry_type) => entry_type, - Err(error) => { - result = result.and(Err(Error::FileTypeError(error))); - continue; - } - }; - - let removal = if entry_type.is_file() || entry_type.is_symlink() { - fs::remove_file(entry.path()).await - } else { - fs::remove_dir_all(entry.path()).await - }; - result = result.and( - removal - .map_err(|e| Error::RemoveDirError(entry.path().display().to_string(), e)), - ); - } - result - } - } - pub fn shutdown_handle(&self) -> DaemonShutdownHandle { DaemonShutdownHandle { tx: self.tx.clone(), |
