rufs/ufs/
symlink.rs

1use super::*;
2use crate::{err, InodeNum};
3
4impl<R: Backend> Ufs<R> {
5	/// Read the contents of a symbolic link.
6	#[doc(alias = "readlink")]
7	pub fn symlink_read(&mut self, inr: InodeNum) -> IoResult<Vec<u8>> {
8		let ino = self.read_inode(inr)?;
9
10		if ino.kind() != InodeType::Symlink {
11			return Err(err!(EINVAL));
12		}
13
14		match &ino.data {
15			InodeData::Shortlink(link) => {
16				assert_eq!(ino.blocks, 0);
17				let len = ino.size as usize;
18				Ok(link[0..len].to_vec())
19			}
20			InodeData::Blocks { .. } => {
21				// TODO: this has to be tested for other configurations, such as 4K/4K
22				assert!(ino.blocks <= 8);
23
24				let len = ino.size as usize;
25				let mut buf = vec![0u8; self.superblock.bsize as usize];
26				self.inode_read_block(inr, &ino, 0, &mut buf)?;
27				buf.resize(len, 0u8);
28				Ok(buf)
29			}
30		}
31	}
32
33	fn symlink_set(&mut self, inr: InodeNum, link: &OsStr) -> IoResult<()> {
34		let mut ino = self.read_inode(inr)?;
35		if ino.kind() != InodeType::Symlink {
36			return Err(err!(EINVAL));
37		}
38
39		assert_eq!(ino.blocks, 0);
40
41		let len = link.len();
42		if len < UFS_SLLEN {
43			let mut data = [0u8; UFS_SLLEN];
44			data[0..len].copy_from_slice(link.as_bytes());
45			ino.data = InodeData::Shortlink(data);
46		} else {
47			todo!("creating long symlinks");
48		}
49		ino.size = len as u64;
50		self.write_inode(inr, &ino)?;
51		Ok(())
52	}
53
54	pub fn symlink(
55		&mut self,
56		dinr: InodeNum,
57		name: &OsStr,
58		link: &OsStr,
59		uid: u32,
60		gid: u32,
61	) -> IoResult<InodeAttr> {
62		self.assert_rw()?;
63		let attr = self.mknod(dinr, name, InodeType::Symlink, 0o777, uid, gid)?;
64		self.symlink_set(attr.inr, link)?;
65		Ok(attr)
66	}
67}