asterinas/kernel/src/fs/procfs/template/builder.rs

221 lines
5.5 KiB
Rust
Raw Normal View History

2024-01-03 03:22:36 +00:00
// SPDX-License-Identifier: MPL-2.0
2023-03-27 05:55:13 +00:00
use super::{
dir::{DirOps, ProcDir},
file::{FileOps, ProcFile},
sym::{ProcSym, SymOps},
};
use crate::{
fs::utils::{FileSystem, Inode, InodeMode},
prelude::*,
};
2023-03-27 05:55:13 +00:00
pub struct ProcDirBuilder<O: DirOps> {
// Mandatory field
dir: O,
mode: InodeMode,
2023-03-27 05:55:13 +00:00
// Optional fields
optional_builder: Option<OptionalBuilder>,
}
impl<O: DirOps> ProcDirBuilder<O> {
pub fn new(dir: O, mode: InodeMode) -> Self {
let optional_builder = OptionalBuilder::new();
2023-03-27 05:55:13 +00:00
Self {
dir,
mode,
2023-03-27 05:55:13 +00:00
optional_builder: Some(optional_builder),
}
}
pub fn parent(self, parent: Weak<dyn Inode>) -> Self {
self.optional_builder(|ob| ob.parent(parent))
}
pub fn fs(self, fs: Weak<dyn FileSystem>) -> Self {
2023-03-27 05:55:13 +00:00
self.optional_builder(|ob| ob.fs(fs))
}
pub fn volatile(self) -> Self {
self.optional_builder(|ob| ob.volatile())
}
pub fn ino(self, ino: u64) -> Self {
self.optional_builder(|ob| ob.ino(ino))
}
2023-03-27 05:55:13 +00:00
pub fn build(mut self) -> Result<Arc<ProcDir<O>>> {
let (fs, parent, ino, is_volatile) = self.optional_builder.take().unwrap().build()?;
Ok(ProcDir::new(
self.dir,
fs,
parent,
ino,
is_volatile,
self.mode,
))
2023-03-27 05:55:13 +00:00
}
fn optional_builder<F>(mut self, f: F) -> Self
where
F: FnOnce(OptionalBuilder) -> OptionalBuilder,
{
let optional_builder = self.optional_builder.take().unwrap();
self.optional_builder = Some(f(optional_builder));
self
}
}
pub struct ProcFileBuilder<O: FileOps> {
// Mandatory field
file: O,
mode: InodeMode,
2023-03-27 05:55:13 +00:00
// Optional fields
optional_builder: Option<OptionalBuilder>,
}
impl<O: FileOps> ProcFileBuilder<O> {
pub fn new(file: O, mode: InodeMode) -> Self {
let optional_builder = OptionalBuilder::new();
2023-03-27 05:55:13 +00:00
Self {
file,
mode,
2023-03-27 05:55:13 +00:00
optional_builder: Some(optional_builder),
}
}
pub fn parent(self, parent: Weak<dyn Inode>) -> Self {
self.optional_builder(|ob| ob.parent(parent))
}
2025-10-24 06:06:55 +00:00
#[expect(dead_code)]
2023-03-27 05:55:13 +00:00
pub fn volatile(self) -> Self {
self.optional_builder(|ob| ob.volatile())
}
pub fn build(mut self) -> Result<Arc<ProcFile<O>>> {
let (fs, _, _, is_volatile) = self.optional_builder.take().unwrap().build()?;
Ok(ProcFile::new(self.file, fs, is_volatile, self.mode))
2023-03-27 05:55:13 +00:00
}
fn optional_builder<F>(mut self, f: F) -> Self
where
F: FnOnce(OptionalBuilder) -> OptionalBuilder,
{
let optional_builder = self.optional_builder.take().unwrap();
self.optional_builder = Some(f(optional_builder));
self
}
}
pub struct ProcSymBuilder<O: SymOps> {
// Mandatory field
sym: O,
mode: InodeMode,
2023-03-27 05:55:13 +00:00
// Optional fields
optional_builder: Option<OptionalBuilder>,
}
impl<O: SymOps> ProcSymBuilder<O> {
pub fn new(sym: O, mode: InodeMode) -> Self {
let optional_builder = OptionalBuilder::new();
2023-03-27 05:55:13 +00:00
Self {
sym,
mode,
2023-03-27 05:55:13 +00:00
optional_builder: Some(optional_builder),
}
}
pub fn parent(self, parent: Weak<dyn Inode>) -> Self {
self.optional_builder(|ob| ob.parent(parent))
}
2025-10-24 06:06:55 +00:00
#[expect(dead_code)]
2023-03-27 05:55:13 +00:00
pub fn volatile(self) -> Self {
self.optional_builder(|ob| ob.volatile())
}
pub fn build(mut self) -> Result<Arc<ProcSym<O>>> {
let (fs, _, _, is_volatile) = self.optional_builder.take().unwrap().build()?;
Ok(ProcSym::new(self.sym, fs, is_volatile, self.mode))
2023-03-27 05:55:13 +00:00
}
fn optional_builder<F>(mut self, f: F) -> Self
where
F: FnOnce(OptionalBuilder) -> OptionalBuilder,
{
let optional_builder = self.optional_builder.take().unwrap();
self.optional_builder = Some(f(optional_builder));
self
}
}
struct OptionalBuilder {
parent: Option<Weak<dyn Inode>>,
fs: Option<Weak<dyn FileSystem>>,
ino: Option<u64>,
2023-03-27 05:55:13 +00:00
is_volatile: bool,
}
impl OptionalBuilder {
fn new() -> Self {
Self {
parent: None,
fs: None,
ino: None,
is_volatile: false,
}
}
2023-03-27 05:55:13 +00:00
pub fn parent(mut self, parent: Weak<dyn Inode>) -> Self {
self.parent = Some(parent);
self
}
pub fn fs(mut self, fs: Weak<dyn FileSystem>) -> Self {
2023-03-27 05:55:13 +00:00
self.fs = Some(fs);
self
}
pub fn ino(mut self, ino: u64) -> Self {
self.ino = Some(ino);
self
}
2023-03-27 05:55:13 +00:00
pub fn volatile(mut self) -> Self {
self.is_volatile = true;
self
}
#[expect(clippy::type_complexity)]
pub fn build(
self,
) -> Result<(
Weak<dyn FileSystem>,
Option<Weak<dyn Inode>>,
Option<u64>,
bool,
)> {
2023-03-27 05:55:13 +00:00
if self.parent.is_none() && self.fs.is_none() {
return_errno_with_message!(Errno::EINVAL, "must have parent or fs");
}
let fs = self.fs.unwrap_or_else(|| {
Arc::downgrade(&self.parent.as_ref().unwrap().upgrade().unwrap().fs())
});
2023-03-27 05:55:13 +00:00
// The volatile property is inherited from parent.
let is_volatile = {
let mut is_volatile = self.is_volatile;
if let Some(parent) = self.parent.as_ref()
&& !parent.upgrade().unwrap().is_dentry_cacheable()
{
is_volatile = true;
2023-03-27 05:55:13 +00:00
}
2023-03-27 05:55:13 +00:00
is_volatile
};
Ok((fs, self.parent, self.ino, is_volatile))
2023-03-27 05:55:13 +00:00
}
}