vfs: add extended attributes

This commit is contained in:
Mark Poliakov 2024-12-04 19:22:08 +02:00
parent 183ec14544
commit cac7306719
8 changed files with 61 additions and 12 deletions

View File

@ -220,11 +220,14 @@ impl Inode {
unsafe { GroupId::from_raw(self.uid as _) }
}
pub fn metadata(&self) -> Metadata {
pub fn metadata(&self, fs: &Ext2Fs, ino: u32) -> Metadata {
Metadata {
uid: self.user_id(),
gid: self.group_id(),
mode: self.mode.permissions(),
inode: Some(ino),
block_count: self.blocks(fs) as _,
block_size: fs.block_size as _,
}
}
}

View File

@ -375,7 +375,7 @@ impl CommonImpl for DirectoryNode {
fn metadata(&self, _node: &NodeRef) -> Result<Metadata, Error> {
let inode = block!(self.inode.get().await)??;
let inode = inode.read();
Ok(inode.metadata())
Ok(inode.metadata(&self.fs, self.inode.ino()))
}
}

View File

@ -105,7 +105,7 @@ impl CommonImpl for RegularNode {
fn metadata(&self, _node: &NodeRef) -> Result<Metadata, Error> {
let inode = block!(self.inode.get().await)??;
let inode = inode.read();
Ok(inode.metadata())
Ok(inode.metadata(&self.fs, self.inode.ino()))
}
fn as_any(&self) -> &dyn Any {

View File

@ -84,7 +84,7 @@ impl CommonImpl for SymlinkNode {
fn metadata(&self, _node: &NodeRef) -> Result<Metadata, Error> {
let inode = block!(self.inode.get().await)??;
let inode = inode.read();
Ok(inode.metadata())
Ok(inode.metadata(&self.fs, self.inode.ino()))
}
}

View File

@ -98,6 +98,12 @@ pub struct Metadata {
pub gid: GroupId,
/// Access mode of the node
pub mode: FileMode,
/// Filesystem-specific node number
pub inode: Option<u32>,
/// Filesystem-specific block size
pub block_size: u64,
/// Size of the node (without metadata) in units of `block_size`
pub block_count: u64,
}
struct PropertyCache {
@ -119,6 +125,9 @@ impl Metadata {
uid: UserId::root(),
gid: GroupId::root(),
mode: FileMode::new(0o755),
block_size: 0,
block_count: 0,
inode: None,
}
}
@ -127,6 +136,9 @@ impl Metadata {
uid: UserId::root(),
gid: GroupId::root(),
mode: FileMode::new(0o644),
block_size: 0,
block_count: 0,
inode: None,
}
}
}

View File

@ -179,7 +179,6 @@ pub(crate) fn get_metadata(
run_with_io_at(&process, at, |at, mut io| {
let node = if path.is_empty() {
at
// at.ok_or(Error::InvalidArgument)?
} else {
io.ioctx_mut().find(Some(at), path, follow, true)?
};
@ -193,6 +192,9 @@ pub(crate) fn get_metadata(
mode: metadata.mode,
uid: metadata.uid,
gid: metadata.gid,
inode: metadata.inode,
block_count: metadata.block_count,
block_size: metadata.block_size,
});
Ok(())

View File

@ -75,6 +75,14 @@ enum FileType(u32) {
struct FileAttr {
/// Data size for files, UNSPECIFIED for the rest
pub size: u64,
/// Filesystem-specific block size
pub block_size: u64,
/// Number of filesystem blocks (not including metadata) occupied by the entry
pub block_count: u64,
/// Filesystem-specific node number
pub inode: Option<u32>,
/// Entry type
pub ty: FileType,
/// Entry access permissions

View File

@ -5,7 +5,8 @@ use std::{
fmt,
fs::{read_dir, FileType, Metadata},
io,
path::{Path, PathBuf}, process::ExitCode,
path::{Path, PathBuf},
process::ExitCode,
};
#[cfg(unix)]
@ -21,6 +22,8 @@ use humansize::{FormatSize, BINARY};
pub struct Args {
#[arg(short)]
long: bool,
#[arg(short)]
inodes: bool,
#[arg(short, long)]
human_readable: bool,
@ -105,11 +108,25 @@ impl DisplayBit for Option<FileType> {
impl DisplayBit for Option<Metadata> {
fn display_bit(&self, opts: &Args, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Some(attrs) = self else {
return write!(f, "--------- {:<8}", "???");
write!(f, "--------- {:<12}", "???")?;
if opts.inodes {
write!(f, " {:<8}", "---")?;
}
return Ok(());
};
let mode = attrs.mode_ext();
write!(f, "{} {:>8}", mode, attrs.len().display_size_with(opts))
write!(f, "{} {:>12}", mode, attrs.len().display_size_with(opts))?;
if opts.inodes {
if let Some(ino) = attrs.inode() {
write!(f, " {:>8}", ino)?;
} else {
write!(f, " {:>8}", "---")?;
}
}
Ok(())
}
}
@ -129,6 +146,8 @@ impl DisplayBit for Option<Metadata> {
impl DisplayBit for Entry {
fn display_bit(&self, opts: &Args, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let ino = self.attrs.as_ref().and_then(MetadataExt::inode);
if opts.long {
write!(
f,
@ -144,6 +163,13 @@ impl DisplayBit for Entry {
Ok(())
} else {
if opts.inodes {
if let Some(ino) = ino {
write!(f, "{ino:<8} ")?;
} else {
write!(f, "{:<8} ", "---")?;
}
}
f.write_str(&self.name)
}
}
@ -191,9 +217,7 @@ fn list_directory(path: &Path) -> io::Result<Vec<Entry>> {
});
}
entries.sort_by(|a, b| {
Ord::cmp(&a.name, &b.name)
});
entries.sort_by(|a, b| Ord::cmp(&a.name, &b.name));
Ok(entries)
}
@ -255,7 +279,7 @@ pub fn main() -> ExitCode {
let results = run(&args);
let code = match results.iter().any(|e| e.is_err()) {
false => ExitCode::SUCCESS,
true => ExitCode::FAILURE
true => ExitCode::FAILURE,
};
code