summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2022-04-04 14:46:53 +0200
committerDavid Lönnhager <david.l@mullvad.net>2022-04-04 15:03:52 +0200
commitcdc33a27d5b30a23ca4b1fffe7ab19dccad966ed (patch)
tree765de974a458497a64dc799bfc3cb34b580a9abc
parent48e3c644b4c6c94a6be80706522a57b0b96acadc (diff)
downloadmullvadvpn-cdc33a27d5b30a23ca4b1fffe7ab19dccad966ed.tar.xz
mullvadvpn-cdc33a27d5b30a23ca4b1fffe7ab19dccad966ed.zip
Distinguish between empty history and parsing errors when reading the old account history format
-rw-r--r--mullvad-daemon/src/migrations/account_history.rs68
1 files changed, 36 insertions, 32 deletions
diff --git a/mullvad-daemon/src/migrations/account_history.rs b/mullvad-daemon/src/migrations/account_history.rs
index 5400f04e33..54f07b8b32 100644
--- a/mullvad-daemon/src/migrations/account_history.rs
+++ b/mullvad-daemon/src/migrations/account_history.rs
@@ -5,7 +5,7 @@ use serde::Deserialize;
use std::path::Path;
use talpid_types::ErrorExt;
use tokio::{
- fs,
+ fs::{self, File},
io::{self, AsyncReadExt, AsyncSeekExt, AsyncWriteExt},
};
@@ -63,29 +63,21 @@ pub async fn migrate_formats(settings_dir: &Path, settings: &mut serde_json::Val
if is_format_v3(&bytes) {
return Ok(());
}
-
- let token = migrate_formats_inner(&bytes, settings)?;
-
- file.set_len(0).await.map_err(Error::WriteHistoryError)?;
- file.seek(io::SeekFrom::Start(0))
- .await
- .map_err(Error::WriteHistoryError)?;
- file.write_all(token.as_bytes())
- .await
- .map_err(Error::WriteHistoryError)?;
- file.sync_all().await.map_err(Error::WriteHistoryError)?;
-
- Ok(())
+ write_format_v3(file, migrate_formats_inner(&bytes, settings)?).await
}
fn migrate_formats_inner(
account_bytes: &[u8],
settings: &mut serde_json::Value,
-) -> Result<AccountToken> {
- if let Some((token, wg_data)) = try_format_v2(account_bytes) {
- settings["wireguard"] = wg_data;
- Ok(token)
- } else if let Some(token) = try_format_v1(account_bytes) {
+) -> Result<Option<AccountToken>> {
+ if let Ok(result) = try_format_v2(account_bytes) {
+ if let Some((token, wg_data)) = result {
+ settings["wireguard"] = wg_data;
+ Ok(Some(token))
+ } else {
+ Ok(None)
+ }
+ } else if let Ok(token) = try_format_v1(account_bytes) {
Ok(token)
} else {
Err(Error::ParseHistoryError)
@@ -99,30 +91,42 @@ fn is_format_v3(bytes: &[u8]) -> bool {
}
}
-fn try_format_v2(bytes: &[u8]) -> Option<(AccountToken, serde_json::Value)> {
+async fn write_format_v3(mut file: File, token: Option<AccountToken>) -> Result<()> {
+ file.set_len(0).await.map_err(Error::WriteHistoryError)?;
+ file.seek(io::SeekFrom::Start(0))
+ .await
+ .map_err(Error::WriteHistoryError)?;
+ if let Some(token) = token {
+ file.write_all(token.as_bytes())
+ .await
+ .map_err(Error::WriteHistoryError)?;
+ }
+ file.sync_all().await.map_err(Error::WriteHistoryError)
+}
+
+fn try_format_v2(bytes: &[u8]) -> Result<Option<(AccountToken, serde_json::Value)>> {
#[derive(Deserialize, Clone)]
pub struct AccountEntry {
pub account: AccountToken,
pub wireguard: serde_json::Value,
}
- serde_json::from_slice(bytes)
- .ok()
- .and_then(|entries: Vec<AccountEntry>| {
- entries
- .into_iter()
- .next()
- .map(|entry| (entry.account, entry.wireguard))
- })
+ Ok(serde_json::from_slice::<'_, Vec<AccountEntry>>(bytes)
+ .map_err(|_error| Error::ParseHistoryError)?
+ .into_iter()
+ .next()
+ .map(|entry| (entry.account, entry.wireguard)))
}
-fn try_format_v1(bytes: &[u8]) -> Option<AccountToken> {
+fn try_format_v1(bytes: &[u8]) -> Result<Option<AccountToken>> {
#[derive(Deserialize)]
struct OldFormat {
accounts: Vec<AccountToken>,
}
- serde_json::from_slice(bytes)
- .ok()
- .and_then(|old_format: OldFormat| old_format.accounts.into_iter().next())
+ Ok(serde_json::from_slice::<'_, OldFormat>(bytes)
+ .map_err(|_error| Error::ParseHistoryError)?
+ .accounts
+ .into_iter()
+ .next())
}
#[cfg(test)]