96 lines
2.4 KiB
Rust
Raw Normal View History

2024-08-02 17:04:47 +03:00
use core::any::Any;
use alloc::{string::String, sync::Arc, vec::Vec};
use libk::{
block,
error::Error,
vfs::{CommonImpl, Metadata, Node, NodeFlags, NodeRef, SymlinkImpl},
};
use libk_util::sync::spin_rwlock::IrqSafeRwLock;
use crate::{Ext2Fs, Inode};
pub struct SymlinkNode {
fs: Arc<Ext2Fs>,
inode: Inode,
#[allow(unused)]
ino: u32,
cache: IrqSafeRwLock<Vec<u8>>,
}
impl SymlinkNode {
pub fn new(fs: Arc<Ext2Fs>, inode: Inode, ino: u32) -> NodeRef {
Node::symlink(
Self {
fs,
inode,
ino,
cache: IrqSafeRwLock::new(Vec::new()),
},
NodeFlags::empty(),
)
}
async fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
let len = self.inode.size_lower as usize;
if len >= self.fs.block_size {
todo!()
}
let mut write = self.cache.write();
write.clear();
// If length of symlink is lower than 60, data is stored directly in "block address"
// section of the inode
if len < 60 {
let bytes = unsafe { self.link_from_inode_blocks(len) };
write.extend_from_slice(bytes);
buf[..len].copy_from_slice(bytes);
} else {
let block = self.fs.inode_block(&self.inode, 0).await?;
write.extend_from_slice(&block[..len]);
buf[..len].copy_from_slice(&block[..len]);
}
Ok(len)
}
unsafe fn link_from_inode_blocks(&self, len: usize) -> &[u8] {
debug_assert!(len < 60);
&bytemuck::bytes_of(&self.inode.blocks)[..len]
}
}
impl CommonImpl for SymlinkNode {
fn size(&self, node: &NodeRef) -> Result<u64, Error> {
Ok(self.inode.size_lower as _)
}
fn as_any(&self) -> &dyn Any {
self
}
fn metadata(&self, node: &NodeRef) -> Result<Metadata, Error> {
Ok(self.inode.metadata())
}
}
impl SymlinkImpl for SymlinkNode {
fn read_link(&self, buf: &mut [u8]) -> Result<usize, Error> {
if buf.len() < self.inode.size_lower as usize {
todo!()
}
{
let read = self.cache.read();
if !read.is_empty() {
buf[..read.len()].copy_from_slice(&read[..]);
return Ok(read.len());
}
}
block!(self.read(buf).await)?
}
}