mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-24 00:01:03 +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)
|
||||
}
|
||||
|
||||
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> {
|
||||
let value = self.value(key)?;
|
||||
#[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) {
|
||||
_ = tokio::task::spawn_blocking(move || {
|
||||
let mut guard = me.write();
|
||||
|
|
@ -75,11 +90,24 @@ impl Partitions {
|
|||
{
|
||||
let set = &self.linux_cache;
|
||||
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.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();
|
||||
for mount in &mut mounts {
|
||||
if !mount.src.as_bytes().starts_with(b"/dev/") {
|
||||
|
|
@ -88,6 +116,8 @@ impl Partitions {
|
|||
if let Ok(meta) = std::fs::metadata(&mount.src) {
|
||||
mount.rdev = Some(meta.rdev() as _);
|
||||
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)
|
||||
|
|
@ -111,21 +141,6 @@ impl Partitions {
|
|||
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> {
|
||||
let mut map = HashMap::new();
|
||||
let Ok(it) = std::fs::read_dir("/dev/disk/by-label") else {
|
||||
|
|
|
|||
|
|
@ -115,6 +115,8 @@ impl Partitions {
|
|||
fstype: dict.os_string("DAVolumeKind").ok(),
|
||||
label: dict.os_string("DAVolumeName").ok(),
|
||||
capacity: dict.integer("DAMediaSize").unwrap_or_default() as u64,
|
||||
external: dict.bool("DADeviceInternal").ok().map(|b| !b),
|
||||
removable: dict.bool("DAMediaRemovable").ok(),
|
||||
..partition
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,15 @@ use std::{ffi::OsString, path::PathBuf};
|
|||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Partition {
|
||||
pub src: OsString,
|
||||
pub dist: Option<PathBuf>,
|
||||
pub src: OsString,
|
||||
pub dist: Option<PathBuf>,
|
||||
#[cfg(unix)]
|
||||
pub rdev: Option<libc::dev_t>,
|
||||
pub label: Option<OsString>,
|
||||
pub fstype: Option<OsString>,
|
||||
pub capacity: u64,
|
||||
pub rdev: Option<libc::dev_t>,
|
||||
pub label: Option<OsString>,
|
||||
pub fstype: Option<OsString>,
|
||||
pub capacity: u64,
|
||||
pub external: Option<bool>,
|
||||
pub removable: Option<bool>,
|
||||
}
|
||||
|
||||
impl Partition {
|
||||
|
|
@ -44,7 +46,24 @@ impl Partition {
|
|||
|
||||
#[inline]
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(super) fn dev_name(&self) -> Option<&std::ffi::OsStr> {
|
||||
std::path::Path::new(&self.src).strip_prefix("/dev/").ok().map(|p| p.as_os_str())
|
||||
pub(super) fn dev_name(&self, full: bool) -> Option<&std::ffi::OsStr> {
|
||||
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)?),
|
||||
("label", p.label.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>>>()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue