mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
feat: new external and removable fields in the fs.partitions() API (#2343)
This commit is contained in:
parent
38e45c647b
commit
22c8f370dc
5 changed files with 68 additions and 24 deletions
|
|
@ -27,6 +27,12 @@ impl CFDict {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn bool(&self, key: &str) -> Result<bool> {
|
||||||
|
let value = self.value(key)?;
|
||||||
|
#[allow(unexpected_cfgs)]
|
||||||
|
Ok(unsafe { msg_send![value as *const Object, boolValue] })
|
||||||
|
}
|
||||||
|
|
||||||
pub fn integer(&self, key: &str) -> Result<i64> {
|
pub fn integer(&self, key: &str) -> Result<i64> {
|
||||||
let value = self.value(key)?;
|
let value = self.value(key)?;
|
||||||
#[allow(unexpected_cfgs)]
|
#[allow(unexpected_cfgs)]
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,21 @@ impl Partitions {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn partitions() -> Result<HashSet<String>> {
|
||||||
|
let mut set = HashSet::new();
|
||||||
|
let s = std::fs::read_to_string("/proc/partitions")?;
|
||||||
|
for line in s.lines().skip(2) {
|
||||||
|
let mut it = line.split_whitespace();
|
||||||
|
let Some(Ok(_major)) = it.next().map(|s| s.parse::<u16>()) else { continue };
|
||||||
|
let Some(Ok(_minor)) = it.next().map(|s| s.parse::<u16>()) else { continue };
|
||||||
|
let Some(Ok(_blocks)) = it.next().map(|s| s.parse::<u32>()) else { continue };
|
||||||
|
if let Some(name) = it.next() {
|
||||||
|
set.insert(Self::unmangle_octal(name).into_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(set)
|
||||||
|
}
|
||||||
|
|
||||||
async fn update(me: Locked) {
|
async fn update(me: Locked) {
|
||||||
_ = tokio::task::spawn_blocking(move || {
|
_ = tokio::task::spawn_blocking(move || {
|
||||||
let mut guard = me.write();
|
let mut guard = me.write();
|
||||||
|
|
@ -75,11 +90,24 @@ impl Partitions {
|
||||||
{
|
{
|
||||||
let set = &self.linux_cache;
|
let set = &self.linux_cache;
|
||||||
let mut set: HashSet<&OsStr> = set.iter().map(AsRef::as_ref).collect();
|
let mut set: HashSet<&OsStr> = set.iter().map(AsRef::as_ref).collect();
|
||||||
mounts.iter().filter_map(|p| p.dev_name()).for_each(|s| _ = set.remove(s));
|
mounts.iter().filter_map(|p| p.dev_name(true)).for_each(|s| _ = set.remove(s));
|
||||||
mounts.extend(set.into_iter().map(Partition::new));
|
mounts.extend(set.into_iter().map(Partition::new));
|
||||||
mounts.sort_unstable_by(|a, b| natsort(a.src.as_bytes(), b.src.as_bytes(), false));
|
mounts.sort_unstable_by(|a, b| natsort(a.src.as_bytes(), b.src.as_bytes(), false));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut removable: HashMap<OsString, Option<bool>> =
|
||||||
|
mounts.iter().filter_map(|p| p.dev_name(false)).map(|s| (s.to_owned(), None)).collect();
|
||||||
|
for (s, b) in &mut removable {
|
||||||
|
match std::fs::read(format!("/sys/block/{}/removable", s.to_string_lossy()))
|
||||||
|
.unwrap_or_default()
|
||||||
|
.trim_ascii()
|
||||||
|
{
|
||||||
|
b"0" => *b = Some(false),
|
||||||
|
b"1" => *b = Some(true),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let labels = Self::labels();
|
let labels = Self::labels();
|
||||||
for mount in &mut mounts {
|
for mount in &mut mounts {
|
||||||
if !mount.src.as_bytes().starts_with(b"/dev/") {
|
if !mount.src.as_bytes().starts_with(b"/dev/") {
|
||||||
|
|
@ -88,6 +116,8 @@ impl Partitions {
|
||||||
if let Ok(meta) = std::fs::metadata(&mount.src) {
|
if let Ok(meta) = std::fs::metadata(&mount.src) {
|
||||||
mount.rdev = Some(meta.rdev() as _);
|
mount.rdev = Some(meta.rdev() as _);
|
||||||
mount.label = labels.get(&(meta.dev(), meta.ino())).cloned();
|
mount.label = labels.get(&(meta.dev(), meta.ino())).cloned();
|
||||||
|
// TODO: mount.external
|
||||||
|
mount.removable = mount.dev_name(false).and_then(|s| removable.get(s).copied()).flatten();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(mounts)
|
Ok(mounts)
|
||||||
|
|
@ -111,21 +141,6 @@ impl Partitions {
|
||||||
Ok(vec)
|
Ok(vec)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn partitions() -> Result<HashSet<String>> {
|
|
||||||
let mut set = HashSet::new();
|
|
||||||
let s = std::fs::read_to_string("/proc/partitions")?;
|
|
||||||
for line in s.lines().skip(2) {
|
|
||||||
let mut it = line.split_whitespace();
|
|
||||||
let Some(Ok(_major)) = it.next().map(|s| s.parse::<u16>()) else { continue };
|
|
||||||
let Some(Ok(_minor)) = it.next().map(|s| s.parse::<u16>()) else { continue };
|
|
||||||
let Some(Ok(_blocks)) = it.next().map(|s| s.parse::<u32>()) else { continue };
|
|
||||||
if let Some(name) = it.next() {
|
|
||||||
set.insert(Self::unmangle_octal(name).into_owned());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(set)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn labels() -> HashMap<(u64, u64), OsString> {
|
fn labels() -> HashMap<(u64, u64), OsString> {
|
||||||
let mut map = HashMap::new();
|
let mut map = HashMap::new();
|
||||||
let Ok(it) = std::fs::read_dir("/dev/disk/by-label") else {
|
let Ok(it) = std::fs::read_dir("/dev/disk/by-label") else {
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,8 @@ impl Partitions {
|
||||||
fstype: dict.os_string("DAVolumeKind").ok(),
|
fstype: dict.os_string("DAVolumeKind").ok(),
|
||||||
label: dict.os_string("DAVolumeName").ok(),
|
label: dict.os_string("DAVolumeName").ok(),
|
||||||
capacity: dict.integer("DAMediaSize").unwrap_or_default() as u64,
|
capacity: dict.integer("DAMediaSize").unwrap_or_default() as u64,
|
||||||
|
external: dict.bool("DADeviceInternal").ok().map(|b| !b),
|
||||||
|
removable: dict.bool("DAMediaRemovable").ok(),
|
||||||
..partition
|
..partition
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,15 @@ use std::{ffi::OsString, path::PathBuf};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Partition {
|
pub struct Partition {
|
||||||
pub src: OsString,
|
pub src: OsString,
|
||||||
pub dist: Option<PathBuf>,
|
pub dist: Option<PathBuf>,
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub rdev: Option<libc::dev_t>,
|
pub rdev: Option<libc::dev_t>,
|
||||||
pub label: Option<OsString>,
|
pub label: Option<OsString>,
|
||||||
pub fstype: Option<OsString>,
|
pub fstype: Option<OsString>,
|
||||||
pub capacity: u64,
|
pub capacity: u64,
|
||||||
|
pub external: Option<bool>,
|
||||||
|
pub removable: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Partition {
|
impl Partition {
|
||||||
|
|
@ -44,7 +46,24 @@ impl Partition {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
pub(super) fn dev_name(&self) -> Option<&std::ffi::OsStr> {
|
pub(super) fn dev_name(&self, full: bool) -> Option<&std::ffi::OsStr> {
|
||||||
std::path::Path::new(&self.src).strip_prefix("/dev/").ok().map(|p| p.as_os_str())
|
use std::os::unix::ffi::OsStrExt;
|
||||||
|
|
||||||
|
let s = std::path::Path::new(&self.src).strip_prefix("/dev/").ok()?.as_os_str();
|
||||||
|
if full {
|
||||||
|
return Some(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
let b = s.as_bytes();
|
||||||
|
if b.len() < 3 {
|
||||||
|
None
|
||||||
|
} else if b.starts_with(b"sd") || b.starts_with(b"hd") || b.starts_with(b"vd") {
|
||||||
|
Some(std::ffi::OsStr::from_bytes(&b[..3]))
|
||||||
|
} else if b.starts_with(b"nvme") || b.starts_with(b"mmcblk") {
|
||||||
|
let n = b.iter().position(|&b| b == b'p').unwrap_or(b.len());
|
||||||
|
Some(std::ffi::OsStr::from_bytes(&b[..n]))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,8 @@ fn partitions(lua: &Lua) -> mlua::Result<Function> {
|
||||||
("dist", p.dist.clone().into_lua(&lua)?),
|
("dist", p.dist.clone().into_lua(&lua)?),
|
||||||
("label", p.label.clone().into_lua(&lua)?),
|
("label", p.label.clone().into_lua(&lua)?),
|
||||||
("fstype", p.fstype.clone().into_lua(&lua)?),
|
("fstype", p.fstype.clone().into_lua(&lua)?),
|
||||||
|
("external", p.external.into_lua(&lua)?),
|
||||||
|
("removable", p.removable.into_lua(&lua)?),
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
.collect::<mlua::Result<Vec<Table>>>()
|
.collect::<mlua::Result<Vec<Table>>>()
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue