//! Open files: what a file descriptor refers to. //! //! `File` is the interface the read/write syscalls use. It's separate from //! `Inode` because the same inode can be open several times with different //! offsets, and because some files aren't in any file system at all (the //! console). Linux calls this `struct file` + `file_operations`. use super::{Inode, InodeKind}; use crate::errno::Errno; use alloc::sync::Arc; use spin::Mutex; pub trait File: Send + Sync { /// Read up to `buf.len()` bytes; 0 means end of file. fn read(&self, buf: &mut [u8]) -> Result; /// Write bytes; returns how many were written. fn write(&self, buf: &[u8]) -> Result; } /// A regular file opened through the VFS: inode + current position. pub struct InodeFile { inode: Arc, offset: Mutex, } impl InodeFile { pub fn open(inode: Arc) -> Result { if inode.kind() == InodeKind::Directory { return Err(Errno::EISDIR); // no getdents yet } Ok(InodeFile { inode, offset: Mutex::new(0) }) } } impl File for InodeFile { fn read(&self, buf: &mut [u8]) -> Result { let mut offset = self.offset.lock(); let n = self.inode.read_at(*offset, buf)?; *offset += n; Ok(n) } fn write(&self, buf: &[u8]) -> Result { let mut offset = self.offset.lock(); let n = self.inode.write_at(*offset, buf)?; *offset += n; Ok(n) } }