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}