shared: add better visibility into IO errors
parent
9d69515d19
commit
981f7e8701
|
@ -1,7 +1,7 @@
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
use colored::*;
|
use colored::*;
|
||||||
use serde::{Deserialize, Serialize};
|
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::{
|
use std::{
|
||||||
fs::{File, OpenOptions},
|
fs::{File, OpenOptions},
|
||||||
io::{Read, Seek, SeekFrom, Write},
|
io::{Read, Seek, SeekFrom, Write},
|
||||||
|
@ -23,7 +23,10 @@ pub enum Contents {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DataStore {
|
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 path = path.as_ref();
|
||||||
let mut file = OpenOptions::new()
|
let mut file = OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
|
@ -32,7 +35,7 @@ impl DataStore {
|
||||||
.open(path)
|
.open(path)
|
||||||
.with_path(path)?;
|
.with_path(path)?;
|
||||||
|
|
||||||
if shared::chmod(&file, 0o600)? {
|
if shared::chmod(&file, 0o600).with_path(path)? {
|
||||||
println!(
|
println!(
|
||||||
"{} updated permissions for {} to 0600.",
|
"{} updated permissions for {} to 0600.",
|
||||||
"[!]".yellow(),
|
"[!]".yellow(),
|
||||||
|
@ -56,16 +59,16 @@ impl DataStore {
|
||||||
.with_extension("json")
|
.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])?;
|
ensure_dirs_exist(&[*CLIENT_DATA_PATH])?;
|
||||||
Self::open_with_path(Self::get_path(interface), create)
|
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)
|
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)
|
Self::_open(interface, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -400,7 +400,7 @@ fn fetch(
|
||||||
let mut store = DataStore::open_or_create(&interface)?;
|
let mut store = DataStore::open_or_create(&interface)?;
|
||||||
let State { peers, cidrs } = Api::new(&config.server).http("GET", "/user/state")?;
|
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
|
let interface_public_key = device_info
|
||||||
.public_key
|
.public_key
|
||||||
.as_ref()
|
.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| {
|
let devices = interfaces.into_iter().filter_map(|name| {
|
||||||
DataStore::open(&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()
|
.ok()
|
||||||
});
|
});
|
||||||
for (mut device_info, store) in devices {
|
for (mut device_info, store) in devices {
|
||||||
|
|
|
@ -31,22 +31,22 @@ pub type Error = Box<dyn std::error::Error>;
|
||||||
pub static WG_MANAGE_DIR: &str = "/etc/innernet";
|
pub static WG_MANAGE_DIR: &str = "/etc/innernet";
|
||||||
pub static WG_DIR: &str = "/etc/wireguard";
|
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 {
|
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 => {
|
Err(e) if e.kind() != io::ErrorKind::AlreadyExists => {
|
||||||
return Err(e.into());
|
return Err(e.into());
|
||||||
},
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let target_file = File::open(dir).with_path(dir)?;
|
let target_file = File::open(dir).with_path(dir)?;
|
||||||
if chmod(&target_file, 0o700)? {
|
if chmod(&target_file, 0o700).with_path(dir)? {
|
||||||
println!(
|
println!(
|
||||||
"{} updated permissions for {} to 0700.",
|
"{} updated permissions for {} to 0700.",
|
||||||
"[!]".yellow(),
|
"[!]".yellow(),
|
||||||
dir.display()
|
dir.display()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
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
|
/// Updates the permissions of a file or directory. Returns `Ok(true)` if
|
||||||
/// permissions had to be changed, `Ok(false)` if permissions were already
|
/// permissions had to be changed, `Ok(false)` if permissions were already
|
||||||
/// correct.
|
/// 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 metadata = file.metadata()?;
|
||||||
let mut permissions = metadata.permissions();
|
let mut permissions = metadata.permissions();
|
||||||
let mode = permissions.mode() & 0o777;
|
let mode = permissions.mode() & 0o777;
|
||||||
|
|
|
@ -73,7 +73,7 @@ impl FromStr for Endpoint {
|
||||||
let port = port.parse().map_err(|_| "couldn't parse port")?;
|
let port = port.parse().map_err(|_| "couldn't parse port")?;
|
||||||
let host = Host::parse(host).map_err(|_| "couldn't parse host")?;
|
let host = Host::parse(host).map_err(|_| "couldn't parse host")?;
|
||||||
Ok(Endpoint { host, port })
|
Ok(Endpoint { host, port })
|
||||||
},
|
}
|
||||||
_ => Err("couldn't parse in form of '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 {}
|
impl std::error::Error for WrappedIoError {}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -252,6 +252,7 @@ impl DeviceInfo {
|
||||||
if backends::kernel::exists() {
|
if backends::kernel::exists() {
|
||||||
backends::kernel::get_by_name(name)
|
backends::kernel::get_by_name(name)
|
||||||
} else {
|
} else {
|
||||||
|
println!("kernel module not detected. falling back to userspace backend.");
|
||||||
backends::userspace::get_by_name(name)
|
backends::userspace::get_by_name(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue