summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorEmīls Piņķis <emils@mullvad.net>2019-07-25 18:04:39 +0100
committerEmīls Piņķis <emils@mullvad.net>2019-07-25 18:05:50 +0100
commite2e1f468f3f24e34dca70ec9ab644e1fb5d91608 (patch)
treeb0bcd410696908ab4c46b3b906ca18e3d8c42f2f
parent63fce125ca7d13727374ed2a12aaf4c478b0cb83 (diff)
downloadmullvadvpn-e2e1f468f3f24e34dca70ec9ab644e1fb5d91608.tar.xz
mullvadvpn-e2e1f468f3f24e34dca70ec9ab644e1fb5d91608.zip
Rework factory-reset in daemon
-rw-r--r--mullvad-daemon/src/lib.rs124
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(),