improve ping behaviour
This commit is contained in:
parent
d71e515050
commit
fa04e70d44
1002
Cargo.lock
generated
1002
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -10,7 +10,8 @@ anyhow = "1.0.86"
|
||||
dns-lookup = "2.0.4"
|
||||
mountinfo = "0.2.0"
|
||||
ping = "0.5.2"
|
||||
sys-mount = "3.0.1"
|
||||
sys-mount = {version="3.0.1", default-features = false}
|
||||
notify-rust = "4"
|
||||
|
||||
[[bin]]
|
||||
name = "automount"
|
||||
|
118
src/main.rs
118
src/main.rs
@ -1,64 +1,96 @@
|
||||
use anyhow::Result;
|
||||
use dns_lookup::lookup_host;
|
||||
use mountinfo::{MountInfo, ReadWrite, MountPoint};
|
||||
use notify_rust::Notification;
|
||||
use ping::{dgramsock, rawsock::ping};
|
||||
use std::{ffi::OsStr, fs, path::PathBuf, sync::mpsc::{self, Receiver, Sender}, thread, time::Duration};
|
||||
use std::{ffi::OsStr, fs, net::IpAddr, path::PathBuf, sync::mpsc::{self, Receiver, Sender}, thread::{self, sleep}, time::Duration};
|
||||
use sys_mount::{unmount, UnmountFlags};
|
||||
|
||||
fn main() {
|
||||
let mtab = MountInfo::new().unwrap();
|
||||
let mounting_points = mtab.mounting_points;
|
||||
let relevant_mounts = mounting_points.iter().filter(|&mount_point| {
|
||||
match &mount_point.fstype {
|
||||
mountinfo::FsType::Other(fsstring) => match fsstring.as_str() {
|
||||
"cifs" => {
|
||||
true
|
||||
|
||||
loop {
|
||||
let mtab = MountInfo::new().unwrap();
|
||||
let mounting_points = mtab.mounting_points;
|
||||
let relevant_mounts = mounting_points.iter().filter(|&mount_point| {
|
||||
match &mount_point.fstype {
|
||||
mountinfo::FsType::Other(fsstring) => match fsstring.as_str() {
|
||||
"cifs" => {
|
||||
true
|
||||
},
|
||||
_ => false
|
||||
},
|
||||
_ => false
|
||||
},
|
||||
_ => false
|
||||
}
|
||||
});
|
||||
|
||||
for mount_point in relevant_mounts {
|
||||
let path = mount_point.path.to_owned();
|
||||
let fstype = match &mount_point.fstype {
|
||||
mountinfo::FsType::Other(fsstring) => fsstring,
|
||||
_ => ""
|
||||
};
|
||||
let what = &mount_point.what;
|
||||
//println!("Processing {fstype} @ {path:?} from {what}");
|
||||
process_mount(fstype, what, path);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
println!("Scanning for hanging mounts");
|
||||
for mount_point in relevant_mounts {
|
||||
let path = mount_point.path.to_owned();
|
||||
let fstype = match &mount_point.fstype {
|
||||
mountinfo::FsType::Other(fsstring) => fsstring,
|
||||
_ => ""
|
||||
};
|
||||
let what = &mount_point.what;
|
||||
println!("Processing {fstype} @ {path:?} from {what}");
|
||||
process_mount(fstype, what, path);
|
||||
|
||||
sleep(Duration::from_secs(5));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn ping_unreachable(host: &IpAddr, repeat:u8 ) -> bool{
|
||||
for _attempt in 0..repeat {
|
||||
match ping::ping(host.to_owned(),Some(Duration::from_millis(100)),Some(10),None, None, None) {
|
||||
Ok(_) => {
|
||||
return false
|
||||
},
|
||||
Err(_) => {
|
||||
|
||||
},
|
||||
}
|
||||
}
|
||||
println!("All ping failed with error -> unmount");
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
fn process_mount(fstype: &str, what: &String, path: PathBuf) {
|
||||
let mut higher_timeout = false;
|
||||
let mut failed_initial_check = false;
|
||||
match fstype {
|
||||
"cifs" => {
|
||||
let path_parts = what.replace("//","/");
|
||||
let host = path_parts.split("/").nth(1).unwrap();
|
||||
println!("Checking ping to host {host}");
|
||||
let ips = lookup_host(host).unwrap();
|
||||
let ip = ips.first().unwrap();
|
||||
println!("Using ip {ip:?}");
|
||||
match ping::ping(ip.to_owned(),Some(Duration::from_millis(100)),Some(10),None, None, None) {
|
||||
Ok(_) => {
|
||||
println!("Ping ok, proceeding")
|
||||
},
|
||||
Err(err) => {
|
||||
println!("Ping failed with errror {err:?} -> unmount");
|
||||
remove_mount(path.as_os_str());
|
||||
},
|
||||
}
|
||||
failed_initial_check = ping_unreachable(&ip, 5);
|
||||
higher_timeout = true;
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if failed_initial_check {
|
||||
let path_utf8 = path.as_os_str().to_string_lossy();
|
||||
let body = format!("Unmounted {} due to fail online check", path_utf8);
|
||||
|
||||
let timeout = Duration::from_millis(500);
|
||||
println!("Checking file access timeout {timeout:?}");
|
||||
let _ = Notification::new()
|
||||
.summary("Autounmount")
|
||||
.body(body.as_str())
|
||||
.icon("firefox")
|
||||
.show();
|
||||
|
||||
remove_mount(path.as_os_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
let timeout = if higher_timeout {
|
||||
Duration::from_millis(10000)
|
||||
} else {
|
||||
Duration::from_millis(1000)
|
||||
};
|
||||
let (sender, receiver) = mpsc::channel();
|
||||
let path_copy = path.clone();
|
||||
thread::spawn(move || {
|
||||
@ -79,15 +111,25 @@ fn process_mount(fstype: &str, what: &String, path: PathBuf) {
|
||||
let read_successful = receiver.recv_timeout(timeout);
|
||||
match read_successful {
|
||||
Ok(_) => {
|
||||
println!("passed, mount still valid")
|
||||
},
|
||||
Err(err) => {
|
||||
println!("Listing failed with errror {err:?} -> unmount");
|
||||
|
||||
let path_utf8 = path.as_os_str().to_string_lossy();
|
||||
let body = format!("Unmounted {} due to fs operation check timeout out after {}s", path_utf8, timeout.as_secs());
|
||||
|
||||
let _ = Notification::new()
|
||||
.summary("Autounmount")
|
||||
.body(body.as_str())
|
||||
.icon("firefox")
|
||||
.show();
|
||||
|
||||
|
||||
remove_mount(path.as_os_str());
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_mount(path: &OsStr){
|
||||
//unmount(path, UnmountFlags::FORCE | UnmountFlags::DETACH).unwrap()
|
||||
unmount(path, UnmountFlags::FORCE | UnmountFlags::DETACH).unwrap()
|
||||
}
|
Loading…
Reference in New Issue
Block a user