2024-08-02 17:04:47 +03:00
|
|
|
use core::any::Any;
|
|
|
|
|
2024-10-11 15:29:41 +03:00
|
|
|
use alloc::{sync::Arc, vec::Vec};
|
2024-08-02 17:04:47 +03:00
|
|
|
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 {
|
2024-10-11 15:29:41 +03:00
|
|
|
fn size(&self, _node: &NodeRef) -> Result<u64, Error> {
|
2024-08-02 17:04:47 +03:00
|
|
|
Ok(self.inode.size_lower as _)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn as_any(&self) -> &dyn Any {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2024-10-11 15:29:41 +03:00
|
|
|
fn metadata(&self, _node: &NodeRef) -> Result<Metadata, Error> {
|
2024-08-02 17:04:47 +03:00
|
|
|
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)?
|
|
|
|
}
|
|
|
|
}
|