Skip to main content

yash_env/system/
io.rs

1// This file is part of yash, an extended POSIX shell.
2// Copyright (C) 2025 WATANABE Yuki
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17//! Items about I/O operations
18
19use super::Result;
20use super::file_system::OfdAccess;
21use crate::io::Fd;
22use enumset::{EnumSet, EnumSetType};
23
24/// Attributes for file descriptors
25#[derive(Debug, EnumSetType, Hash)]
26#[non_exhaustive]
27pub enum FdFlag {
28    /// Close the file descriptor upon execution of an exec family function
29    CloseOnExec,
30    // TODO CloseOnFork,
31}
32
33/// Trait for closing file descriptors
34pub trait Close {
35    /// Closes a file descriptor.
36    ///
37    /// This is a thin wrapper around the [`close` system
38    /// call](https://pubs.opengroup.org/onlinepubs/9799919799/functions/close.html).
39    ///
40    /// If successful, returns `Ok(())`. On error, returns `Err(_)`.
41    /// This function returns `Ok(())` when the FD is already closed, which is
42    /// different from the behavior of the underlying system call.
43    fn close(&self, fd: Fd) -> Result<()>;
44}
45
46/// Trait for creating pipes
47///
48/// This trait declares the `pipe` method, which creates an unnamed pipe. This
49/// is a wrapper around the `pipe` system call.
50pub trait Pipe {
51    /// Creates an unnamed pipe.
52    ///
53    /// This is a thin wrapper around the [`pipe` system
54    /// call](https://pubs.opengroup.org/onlinepubs/9799919799/functions/pipe.html).
55    /// If successful, returns the reading and writing ends of the pipe.
56    fn pipe(&self) -> Result<(Fd, Fd)>;
57}
58
59/// Trait for duplicating file descriptors
60///
61/// This trait declares the `dup` and `dup2` methods, which duplicate file
62/// descriptors.
63pub trait Dup {
64    /// Duplicates a file descriptor.
65    ///
66    /// This is a thin wrapper around the [`fcntl` system
67    /// call](https://pubs.opengroup.org/onlinepubs/9799919799/functions/fcntl.html)
68    /// that opens a new FD that shares the open file description with `from`.
69    /// The new FD will be the minimum unused FD not less than `to_min`. The
70    /// `flags` are set to the new FD.
71    ///
72    /// If successful, returns `Ok(new_fd)`. On error, returns `Err(_)`.
73    fn dup(&self, from: Fd, to_min: Fd, flags: EnumSet<FdFlag>) -> Result<Fd>;
74
75    /// Duplicates a file descriptor.
76    ///
77    /// This is a thin wrapper around the [`dup2` system
78    /// call](https://pubs.opengroup.org/onlinepubs/9799919799/functions/dup.html).
79    /// If successful, returns `Ok(to)`. On error, returns `Err(_)`.
80    fn dup2(&self, from: Fd, to: Fd) -> Result<Fd>;
81}
82
83/// Trait for `fcntl`-related operations
84///
85/// This trait declares methods related to the [`fcntl` system
86/// call](https://pubs.opengroup.org/onlinepubs/9799919799/functions/fcntl.html)
87/// for manipulating file descriptors and open file descriptions.
88pub trait Fcntl {
89    /// Returns the open file description access mode.
90    fn ofd_access(&self, fd: Fd) -> Result<OfdAccess>;
91
92    /// Gets and sets the non-blocking mode for the open file description.
93    ///
94    /// This function sets the non-blocking mode to the given value and returns
95    /// the previous mode.
96    fn get_and_set_nonblocking(&self, fd: Fd, nonblocking: bool) -> Result<bool>;
97
98    /// Returns the attributes for the file descriptor.
99    fn fcntl_getfd(&self, fd: Fd) -> Result<EnumSet<FdFlag>>;
100
101    /// Sets attributes for the file descriptor.
102    fn fcntl_setfd(&self, fd: Fd, flags: EnumSet<FdFlag>) -> Result<()>;
103}
104
105/// Trait for reading from file descriptors
106pub trait Read {
107    /// Reads from the file descriptor.
108    ///
109    /// This is a thin wrapper around the [`read` system
110    /// call](https://pubs.opengroup.org/onlinepubs/9799919799/functions/read.html).
111    /// If successful, returns the number of bytes read.
112    ///
113    /// This function may perform blocking I/O, especially if the `O_NONBLOCK`
114    /// flag is not set for the FD. Use [`SharedSystem::read_async`] to support
115    /// concurrent I/O in an `async` function context.
116    ///
117    /// [`SharedSystem::read_async`]: super::SharedSystem::read_async
118    ///
119    /// TODO: This function should return a `Future` to support simulating
120    /// blocking I/O in virtual systems.
121    fn read(&self, fd: Fd, buffer: &mut [u8]) -> Result<usize>;
122}
123
124/// Trait for writing to file descriptors
125pub trait Write {
126    /// Writes to the file descriptor.
127    ///
128    /// This is a thin wrapper around the [`write` system
129    /// call](https://pubs.opengroup.org/onlinepubs/9799919799/functions/write.html).
130    /// If successful, returns the number of bytes written.
131    ///
132    /// This function may write only part of the `buffer` and block if the
133    /// `O_NONBLOCK` flag is not set for the FD. Use [`SharedSystem::write_all`]
134    /// to support concurrent I/O in an `async` function context and ensure the
135    /// whole `buffer` is written.
136    ///
137    /// [`SharedSystem::write_all`]: super::SharedSystem::write_all
138    ///
139    /// TODO: This function should return a `Future` to support simulating
140    /// blocking I/O in virtual systems.
141    fn write(&self, fd: Fd, buffer: &[u8]) -> Result<usize>;
142}