Skip to main content

starnix_core/vfs/pseudo/
stub_empty_file.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::task::CurrentTask;
6use crate::vfs::buffers::{InputBuffer, OutputBuffer};
7use crate::vfs::pseudo::simple_file::SimpleFileNode;
8use crate::vfs::{
9    FileObject, FileOps, FsNodeOps, fileops_impl_nonseekable, fileops_impl_noop_sync,
10};
11use bstr::ByteSlice;
12use starnix_logging::BugRef;
13use starnix_uapi::error;
14use starnix_uapi::errors::Errno;
15use std::panic::Location;
16
17#[derive(Clone, Debug)]
18pub struct StubEmptyFile {
19    bug: BugRef,
20    location: &'static Location<'static>,
21}
22
23impl StubEmptyFile {
24    #[track_caller]
25    pub fn new_node(bug: BugRef) -> impl FsNodeOps {
26        SimpleFileNode::new(move |_| Ok(StubEmptyFile::new(bug)))
27    }
28
29    #[track_caller]
30    pub fn new(bug: BugRef) -> Self {
31        // This ensures the caller of this fn is recorded instead of the location of the closure.
32        let location = Location::caller();
33        Self { bug, location }
34    }
35}
36
37impl FileOps for StubEmptyFile {
38    fileops_impl_nonseekable!();
39    fileops_impl_noop_sync!();
40
41    fn open(&self, file: &FileObject, current_task: &CurrentTask) -> Result<(), Errno> {
42        let path = file.name.path(&current_task.fs());
43        starnix_logging::__track_stub_inner(
44            self.bug,
45            path.to_str_lossy().as_ref(),
46            None,
47            &self.location,
48        );
49        Ok(())
50    }
51
52    fn read(
53        &self,
54        _file: &FileObject,
55        _current_task: &CurrentTask,
56        _offset: usize,
57        _data: &mut dyn OutputBuffer,
58    ) -> Result<usize, Errno> {
59        Ok(0)
60    }
61
62    fn write(
63        &self,
64        _file: &FileObject,
65        _current_task: &CurrentTask,
66        _offset: usize,
67        _data: &mut dyn InputBuffer,
68    ) -> Result<usize, Errno> {
69        error!(EINVAL)
70    }
71}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76    use crate::testing::{anon_test_file, spawn_kernel_and_run};
77    use crate::vfs::buffers::{VecInputBuffer, VecOutputBuffer};
78    use starnix_logging::bug_ref;
79    use starnix_uapi::errno;
80    use starnix_uapi::open_flags::OpenFlags;
81
82    #[fuchsia::test]
83    async fn test_stub_empty_file_read_returns_eof() {
84        spawn_kernel_and_run(async |current_task| {
85            let file = anon_test_file(
86                &current_task,
87                Box::new(StubEmptyFile::new(bug_ref!("https://fxbug.dev/574071555"))),
88                OpenFlags::RDWR,
89            );
90
91            let mut out_buf = VecOutputBuffer::new(64);
92            assert_eq!(file.read(&current_task, &mut out_buf), Ok(0));
93            assert!(out_buf.data().is_empty());
94
95            let mut in_buf = VecInputBuffer::new(b"test");
96            assert_eq!(file.write(&current_task, &mut in_buf), Err(errno!(EINVAL)));
97        })
98        .await;
99    }
100}