1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
use anyhow::{anyhow, Result};
use crate::{constant_strings_paths::GIO, impl_selectable_content};
#[derive(Debug, Clone, Default)]
pub struct RemovableDevices {
pub content: Vec<Removable>,
pub index: usize,
}
impl RemovableDevices {
pub fn from_gio() -> Option<Self> {
let Ok(output) = std::process::Command::new(GIO)
.args(["mount", "-li"])
.output()
else {
return None;
};
let Ok(stdout) = String::from_utf8(output.stdout) else {
return None;
};
log::info!("gio {stdout}");
let content: Vec<_> = stdout
.lines()
.filter(|line| line.contains("activation_root"))
.map(|line| line.to_owned())
.map(|line| Removable::from_gio(line))
.filter_map(|removable| removable.ok())
.collect();
if content.is_empty() {
None
} else {
Some(Self { content, index: 0 })
}
}
pub fn current(&mut self) -> Option<&mut Removable> {
if self.content.is_empty() {
None
} else {
Some(&mut self.content[self.index])
}
}
}
#[derive(Debug, Clone, Default)]
pub struct Removable {
pub device_name: String,
pub path: String,
pub is_mounted: bool,
}
impl Removable {
fn from_gio(line: String) -> Result<Self> {
let line = line.replace("activation_root=mtp://", "");
let device_name = line;
let uid = users::get_current_uid();
let path = format!("/run/user/{uid}/gvfs/mtp:host={device_name}");
let pb_path = std::path::Path::new(&path);
let is_mounted = pb_path.exists() && pb_path.read_dir()?.next().is_some();
log::info!("gio {device_name} - is_mounted {is_mounted}");
Ok(Self {
device_name,
path,
is_mounted,
})
}
pub fn mount(&mut self) -> Result<()> {
if self.is_mounted {
return Err(anyhow!("Already mounted {name}", name = self.device_name));
}
self.is_mounted = std::process::Command::new(GIO)
.args(vec![
"mount",
&format!("mtp://{name}", name = self.device_name),
])
.spawn()?
.wait()?
.success();
Ok(())
}
pub fn umount(&mut self) -> Result<()> {
if !self.is_mounted {
return Err(anyhow!("Not mounted {name}", name = self.device_name));
}
self.is_mounted = std::process::Command::new(GIO)
.args(vec![
"mount",
&format!("mtp://{name}", name = self.device_name),
"-u",
])
.spawn()?
.wait()?
.success();
Ok(())
}
}
impl_selectable_content!(Removable, RemovableDevices);
|