shared: add better visibility into IO errors

pull/71/head^2
Jake McGinty 2021-05-09 21:34:11 +09:00
parent 9d69515d19
commit 981f7e8701
5 changed files with 32 additions and 15 deletions

View File

@ -1,7 +1,7 @@
use crate::Error;
use colored::*;
use serde::{Deserialize, Serialize};
use shared::{ensure_dirs_exist, Cidr, IoErrorContext, Peer, CLIENT_DATA_PATH};
use shared::{ensure_dirs_exist, Cidr, IoErrorContext, Peer, WrappedIoError, CLIENT_DATA_PATH};
use std::{
fs::{File, OpenOptions},
io::{Read, Seek, SeekFrom, Write},
@ -23,7 +23,10 @@ pub enum Contents {
}
impl DataStore {
pub(self) fn open_with_path<P: AsRef<Path>>(path: P, create: bool) -> Result<Self, Error> {
pub(self) fn open_with_path<P: AsRef<Path>>(
path: P,
create: bool,
) -> Result<Self, WrappedIoError> {
let path = path.as_ref();
let mut file = OpenOptions::new()
.read(true)
@ -32,7 +35,7 @@ impl DataStore {
.open(path)
.with_path(path)?;
if shared::chmod(&file, 0o600)? {
if shared::chmod(&file, 0o600).with_path(path)? {
println!(
"{} updated permissions for {} to 0600.",
"[!]".yellow(),
@ -56,16 +59,16 @@ impl DataStore {
.with_extension("json")
}
fn _open(interface: &InterfaceName, create: bool) -> Result<Self, Error> {
fn _open(interface: &InterfaceName, create: bool) -> Result<Self, WrappedIoError> {
ensure_dirs_exist(&[*CLIENT_DATA_PATH])?;
Self::open_with_path(Self::get_path(interface), create)
}
pub fn open(interface: &InterfaceName) -> Result<Self, Error> {
pub fn open(interface: &InterfaceName) -> Result<Self, WrappedIoError> {
Self::_open(interface, false)
}
pub fn open_or_create(interface: &InterfaceName) -> Result<Self, Error> {
pub fn open_or_create(interface: &InterfaceName) -> Result<Self, WrappedIoError> {
Self::_open(interface, true)
}

View File

@ -400,7 +400,7 @@ fn fetch(
let mut store = DataStore::open_or_create(&interface)?;
let State { peers, cidrs } = Api::new(&config.server).http("GET", "/user/state")?;
let device_info = DeviceInfo::get_by_name(&interface)?;
let device_info = DeviceInfo::get_by_name(&interface).with_str(interface.as_str_lossy())?;
let interface_public_key = device_info
.public_key
.as_ref()
@ -716,7 +716,12 @@ fn show(short: bool, tree: bool, interface: Option<Interface>) -> Result<(), Err
let devices = interfaces.into_iter().filter_map(|name| {
DataStore::open(&name)
.and_then(|store| Ok((DeviceInfo::get_by_name(&name)?, store)))
.and_then(|store| {
Ok((
DeviceInfo::get_by_name(&name).with_str(name.as_str_lossy())?,
store,
))
})
.ok()
});
for (mut device_info, store) in devices {

View File

@ -31,22 +31,22 @@ pub type Error = Box<dyn std::error::Error>;
pub static WG_MANAGE_DIR: &str = "/etc/innernet";
pub static WG_DIR: &str = "/etc/wireguard";
pub fn ensure_dirs_exist(dirs: &[&Path]) -> Result<(), Error> {
pub fn ensure_dirs_exist(dirs: &[&Path]) -> Result<(), WrappedIoError> {
for dir in dirs {
match fs::create_dir(dir) {
match fs::create_dir(dir).with_path(dir) {
Err(e) if e.kind() != io::ErrorKind::AlreadyExists => {
return Err(e.into());
},
}
_ => {
let target_file = File::open(dir).with_path(dir)?;
if chmod(&target_file, 0o700)? {
if chmod(&target_file, 0o700).with_path(dir)? {
println!(
"{} updated permissions for {} to 0700.",
"[!]".yellow(),
dir.display()
);
}
},
}
}
}
Ok(())
@ -55,7 +55,7 @@ pub fn ensure_dirs_exist(dirs: &[&Path]) -> Result<(), Error> {
/// Updates the permissions of a file or directory. Returns `Ok(true)` if
/// permissions had to be changed, `Ok(false)` if permissions were already
/// correct.
pub fn chmod(file: &File, new_mode: u32) -> Result<bool, Error> {
pub fn chmod(file: &File, new_mode: u32) -> Result<bool, io::Error> {
let metadata = file.metadata()?;
let mut permissions = metadata.permissions();
let mode = permissions.mode() & 0o777;

View File

@ -73,7 +73,7 @@ impl FromStr for Endpoint {
let port = port.parse().map_err(|_| "couldn't parse port")?;
let host = Host::parse(host).map_err(|_| "couldn't parse host")?;
Ok(Endpoint { host, port })
},
}
_ => Err("couldn't parse in form of 'host:port'"),
}
}
@ -606,6 +606,14 @@ impl std::fmt::Display for WrappedIoError {
}
}
impl Deref for WrappedIoError {
type Target = std::io::Error;
fn deref(&self) -> &Self::Target {
&self.io_error
}
}
impl std::error::Error for WrappedIoError {}
#[cfg(test)]

View File

@ -252,6 +252,7 @@ impl DeviceInfo {
if backends::kernel::exists() {
backends::kernel::get_by_name(name)
} else {
println!("kernel module not detected. falling back to userspace backend.");
backends::userspace::get_by_name(name)
}
}