diff options
| author | Emīls Piņķis <emils@mullvad.net> | 2019-07-25 18:04:39 +0100 |
|---|---|---|
| committer | Emīls Piņķis <emils@mullvad.net> | 2019-07-25 18:05:50 +0100 |
| commit | e2e1f468f3f24e34dca70ec9ab644e1fb5d91608 (patch) | |
| tree | b0bcd410696908ab4c46b3b906ca18e3d8c42f2f | |
| parent | 63fce125ca7d13727374ed2a12aaf4c478b0cb83 (diff) | |
| download | mullvadvpn-e2e1f468f3f24e34dca70ec9ab644e1fb5d91608.tar.xz mullvadvpn-e2e1f468f3f24e34dca70ec9ab644e1fb5d91608.zip | |
Rework factory-reset in daemon
| -rw-r--r-- | mullvad-daemon/src/lib.rs | 124 |
1 files changed, 102 insertions, 22 deletions
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs index 076ef3341c..27594c8adf 100644 --- a/mullvad-daemon/src/lib.rs +++ b/mullvad-daemon/src/lib.rs @@ -46,7 +46,9 @@ use mullvad_types::{ wireguard::KeygenEvent, }; use settings::Settings; -use std::{fs, io, mem, path::PathBuf, sync::mpsc, thread, time::Duration}; +#[cfg(not(target_os = "android"))] +use std::path::Path; +use std::{io, mem, path::PathBuf, sync::mpsc, thread, time::Duration}; use talpid_core::{ mpsc::IntoSender, tunnel::tun_provider::{PlatformTunProvider, TunProvider}, @@ -102,14 +104,26 @@ pub enum Error { #[error(display = "Tunnel state machine error")] TunnelError(#[error(cause)] tunnel_state_machine::Error), - #[error(display = "Failed to remove a directory")] - RemovalError(#[error(cause)] io::Error), + #[error(display = "Failed to remove directory {}", _0)] + RemoveDirError(String, #[error(cause)] io::Error), - #[error(display = "Failed to create a directory")] - CreateDirError(#[error(cause)] io::Error), + #[error(display = "Failed to create directory {}", _0)] + CreateDirError(String, #[error(cause)] io::Error), #[error(display = "Failed to get path")] PathError(#[error(cause)] mullvad_paths::Error), + + #[cfg(target_os = "windows")] + #[error(display = "Failed to get file type info")] + FileTypeError(#[error(cause)] io::Error), + + #[cfg(target_os = "windows")] + #[error(display = "Failed to get dir entry")] + FileEntryError(#[error(cause)] io::Error), + + #[cfg(target_os = "windows")] + #[error(display = "Failed to read dir entries")] + ReadDirError(#[error(cause)] io::Error), } type SyncUnboundedSender<T> = ::futures::sink::Wait<UnboundedSender<T>>; @@ -444,12 +458,31 @@ where break; } } - for cb in self.shutdown_callbacks.into_iter() { + + self.finalize(); + Ok(()) + } + + fn finalize(self) { + let (event_listener, shutdown_callbacks) = self.shutdown(); + for cb in shutdown_callbacks { cb(); } - Ok(()) + mem::drop(event_listener); + } + + /// Shuts down the daemon without shutting down the underlying management interface event + /// listener and the shutdown callbacks + fn shutdown(self) -> (L, Vec<Box<dyn FnOnce()>>) { + let Daemon { + event_listener, + shutdown_callbacks, + .. + } = self; + (event_listener, shutdown_callbacks) } + fn handle_event(&mut self, event: InternalDaemonEvent) -> Result<()> { use self::InternalDaemonEvent::*; match event { @@ -682,6 +715,10 @@ where fn handle_management_interface_event(&mut self, event: ManagementCommand) { use self::ManagementCommand::*; + if !self.state.is_running() { + log::trace!("Dropping management command because the daemon is shutting down",); + return; + } match event { SetTargetState(tx, state) => self.on_set_target_state(tx, state), GetState(tx) => self.on_get_state(tx), @@ -952,15 +989,6 @@ where fn on_factory_reset(&mut self, tx: oneshot::Sender<()>) { let mut failed = false; - if let Err(e) = self.clear_cache_directory() { - log::error!("Failed to clear cache directory - {}", e); - failed = true; - } - - if let Err(e) = self.clear_log_directory() { - log::error!("Failed to clear log directory - {}", e); - failed = true; - } if let Err(e) = self.settings.reset() { log::error!("Failed to reset settings - {}", e); @@ -976,6 +1004,21 @@ where self.trigger_shutdown_event(); self.shutdown_callbacks.push(Box::new(move || { + if let Err(e) = Self::clear_cache_directory() { + log::error!( + "{}", + e.display_chain_with_msg("Failed to clear cache directory") + ); + failed = true; + } + + if let Err(e) = Self::clear_log_directory() { + log::error!( + "{}", + e.display_chain_with_msg("Failed to clear log directory") + ); + failed = true; + } if !failed { Self::oneshot_send(tx, (), "factory_reset response"); } @@ -1343,18 +1386,55 @@ where .expect("Tunnel state machine has stopped"); } - fn clear_log_directory(&self) -> Result<()> { + #[cfg(not(target_os = "android"))] + fn clear_log_directory() -> Result<()> { let log_dir = mullvad_paths::get_log_dir().map_err(Error::PathError)?; - fs::remove_dir_all(&log_dir).map_err(Error::RemovalError)?; - fs::create_dir_all(&log_dir).map_err(Error::CreateDirError) + Self::clear_directory(&log_dir) } - fn clear_cache_directory(&self) -> Result<()> { + #[cfg(not(target_os = "android"))] + fn clear_cache_directory() -> Result<()> { let cache_dir = mullvad_paths::cache_dir().map_err(Error::PathError)?; - fs::remove_dir_all(&cache_dir).map_err(Error::RemovalError)?; - fs::create_dir_all(&cache_dir).map_err(Error::CreateDirError) + Self::clear_directory(&cache_dir) + } + + #[cfg(not(target_os = "android"))] + fn clear_directory(path: &Path) -> Result<()> { + use std::fs; + #[cfg(not(target_os = "windows"))] + { + fs::remove_dir_all(path) + .map_err(|e| Error::RemoveDirError(path.display().to_string(), e))?; + fs::create_dir_all(path) + .map_err(|e| Error::CreateDirError(path.display().to_string(), e)) + } + #[cfg(target_os = "windows")] + { + fs::read_dir(&path) + .map_err(Error::ReadDirError) + .and_then(|dir_entries| { + dir_entries + .into_iter() + .map(|entry| { + let entry = entry.map_err(Error::FileEntryError)?; + let entry_type = entry.file_type().map_err(Error::FileTypeError)?; + + + let removal = if entry_type.is_file() || entry_type.is_symlink() { + fs::remove_file(entry.path()) + } else { + fs::remove_dir_all(entry.path()) + }; + removal.map_err(|e| { + Error::RemoveDirError(entry.path().display().to_string(), e) + }) + }) + .collect::<Result<()>>() + }) + } } + pub fn shutdown_handle(&self) -> DaemonShutdownHandle { DaemonShutdownHandle { tx: self.tx.clone(), |
