4186d117af
## Issue Addressed Closes #3049 This PR updates widely but this replace is safe as `File::options()` is equivelent to `OpenOptions::new()`. ref: https://doc.rust-lang.org/stable/src/std/fs.rs.html#378-380
98 lines
3.2 KiB
Rust
98 lines
3.2 KiB
Rust
//! Provides some CRUD functions for wallets on the filesystem.
|
|
|
|
use eth2_wallet::Error as WalletError;
|
|
use eth2_wallet::{Uuid, Wallet};
|
|
use std::fs::{copy as copy_file, remove_file, File};
|
|
use std::io;
|
|
use std::path::{Path, PathBuf};
|
|
|
|
#[derive(Debug)]
|
|
pub enum Error {
|
|
WalletAlreadyExists(PathBuf),
|
|
WalletDoesNotExist(PathBuf),
|
|
WalletBackupAlreadyExists(PathBuf),
|
|
UnableToCreateBackup(io::Error),
|
|
UnableToRemoveBackup(io::Error),
|
|
UnableToRemoveWallet(io::Error),
|
|
UnableToCreateWallet(io::Error),
|
|
UnableToReadWallet(io::Error),
|
|
JsonWrite(WalletError),
|
|
JsonRead(WalletError),
|
|
}
|
|
|
|
/// Read a wallet with the given `uuid` from the `wallet_dir`.
|
|
pub fn read<P: AsRef<Path>>(wallet_dir: P, uuid: &Uuid) -> Result<Wallet, Error> {
|
|
let json_path = wallet_json_path(wallet_dir, uuid);
|
|
|
|
if !json_path.exists() {
|
|
Err(Error::WalletDoesNotExist(json_path))
|
|
} else {
|
|
File::options()
|
|
.read(true)
|
|
.create(false)
|
|
.open(json_path)
|
|
.map_err(Error::UnableToReadWallet)
|
|
.and_then(|f| Wallet::from_json_reader(f).map_err(Error::JsonRead))
|
|
}
|
|
}
|
|
|
|
/// Update the JSON file in the `wallet_dir` with the given `wallet`.
|
|
///
|
|
/// Performs a three-step copy:
|
|
///
|
|
/// 1. Copy the current JSON file to a backup file.
|
|
/// 2. Over-write the existing JSON file.
|
|
/// 3. Delete the backup file.
|
|
pub fn update<P: AsRef<Path>>(wallet_dir: P, wallet: &Wallet) -> Result<(), Error> {
|
|
let wallet_dir = wallet_dir.as_ref();
|
|
|
|
let json_path = wallet_json_path(wallet_dir, wallet.uuid());
|
|
let json_backup_path = wallet_json_backup_path(wallet_dir, wallet.uuid());
|
|
|
|
// Require that a wallet already exists.
|
|
if !json_path.exists() {
|
|
return Err(Error::WalletDoesNotExist(json_path));
|
|
// Require that there is no existing backup.
|
|
} else if json_backup_path.exists() {
|
|
return Err(Error::WalletBackupAlreadyExists(json_backup_path));
|
|
}
|
|
|
|
// Copy the existing wallet to the backup location.
|
|
copy_file(&json_path, &json_backup_path).map_err(Error::UnableToCreateBackup)?;
|
|
|
|
// Remove the existing wallet
|
|
remove_file(json_path).map_err(Error::UnableToRemoveWallet)?;
|
|
|
|
// Create the new wallet.
|
|
create(wallet_dir, wallet)?;
|
|
|
|
// Remove the backup file.
|
|
remove_file(json_backup_path).map_err(Error::UnableToRemoveBackup)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Writes the `wallet` into the `wallet_dir`, returning an error if it already exists.
|
|
pub fn create<P: AsRef<Path>>(wallet_dir: P, wallet: &Wallet) -> Result<(), Error> {
|
|
let json_path = wallet_json_path(wallet_dir, wallet.uuid());
|
|
|
|
if json_path.exists() {
|
|
Err(Error::WalletAlreadyExists(json_path))
|
|
} else {
|
|
File::options()
|
|
.write(true)
|
|
.create_new(true)
|
|
.open(json_path)
|
|
.map_err(Error::UnableToCreateWallet)
|
|
.and_then(|f| wallet.to_json_writer(f).map_err(Error::JsonWrite))
|
|
}
|
|
}
|
|
|
|
fn wallet_json_backup_path<P: AsRef<Path>>(wallet_dir: P, uuid: &Uuid) -> PathBuf {
|
|
wallet_dir.as_ref().join(format!("{}.backup", uuid))
|
|
}
|
|
|
|
fn wallet_json_path<P: AsRef<Path>>(wallet_dir: P, uuid: &Uuid) -> PathBuf {
|
|
wallet_dir.as_ref().join(format!("{}", uuid))
|
|
}
|