1 | //! `read` and `write`, optionally positioned, optionally vectored. |
2 | |
3 | #![allow (unsafe_code)] |
4 | |
5 | use crate::buffer::Buffer; |
6 | use crate::{backend, io}; |
7 | use backend::fd::AsFd; |
8 | |
9 | // Declare `IoSlice` and `IoSliceMut`. |
10 | #[cfg (not(windows))] |
11 | pub use crate::maybe_polyfill::io::{IoSlice, IoSliceMut}; |
12 | |
13 | #[cfg (linux_kernel)] |
14 | pub use backend::io::types::ReadWriteFlags; |
15 | |
16 | /// `read(fd, buf)`—Reads from a stream. |
17 | /// |
18 | /// # References |
19 | /// - [POSIX] |
20 | /// - [Linux] |
21 | /// - [Apple] |
22 | /// - [FreeBSD] |
23 | /// - [NetBSD] |
24 | /// - [OpenBSD] |
25 | /// - [DragonFly BSD] |
26 | /// - [illumos] |
27 | /// - [glibc] |
28 | /// |
29 | /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/read.html |
30 | /// [Linux]: https://man7.org/linux/man-pages/man2/read.2.html |
31 | /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/read.2.html |
32 | /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=read&sektion=2 |
33 | /// [NetBSD]: https://man.netbsd.org/read.2 |
34 | /// [OpenBSD]: https://man.openbsd.org/read.2 |
35 | /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=read§ion=2 |
36 | /// [illumos]: https://illumos.org/man/2/read |
37 | /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/I_002fO-Primitives.html#index-reading-from-a-file-descriptor |
38 | #[inline ] |
39 | pub fn read<Fd: AsFd, Buf: Buffer<u8>>(fd: Fd, mut buf: Buf) -> io::Result<Buf::Output> { |
40 | // SAFETY: `read` behaves. |
41 | let len: usize = unsafe { backend::io::syscalls::read(fd.as_fd(), buf.parts_mut())? }; |
42 | // SAFETY: `read` behaves. |
43 | unsafe { Ok(buf.assume_init(len)) } |
44 | } |
45 | |
46 | /// `write(fd, buf)`—Writes to a stream. |
47 | /// |
48 | /// # References |
49 | /// - [POSIX] |
50 | /// - [Linux] |
51 | /// - [Apple] |
52 | /// - [FreeBSD] |
53 | /// - [NetBSD] |
54 | /// - [OpenBSD] |
55 | /// - [DragonFly BSD] |
56 | /// - [illumos] |
57 | /// - [glibc] |
58 | /// |
59 | /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/write.html |
60 | /// [Linux]: https://man7.org/linux/man-pages/man2/write.2.html |
61 | /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/write.2.html |
62 | /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=write&sektion=2 |
63 | /// [NetBSD]: https://man.netbsd.org/write.2 |
64 | /// [OpenBSD]: https://man.openbsd.org/write.2 |
65 | /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=write§ion=2 |
66 | /// [illumos]: https://illumos.org/man/2/write |
67 | /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/I_002fO-Primitives.html#index-writing-to-a-file-descriptor |
68 | #[inline ] |
69 | pub fn write<Fd: AsFd>(fd: Fd, buf: &[u8]) -> io::Result<usize> { |
70 | backend::io::syscalls::write(fd.as_fd(), buf) |
71 | } |
72 | |
73 | /// `pread(fd, buf, offset)`—Reads from a file at a given position. |
74 | /// |
75 | /// # References |
76 | /// - [POSIX] |
77 | /// - [Linux] |
78 | /// - [Apple] |
79 | /// - [FreeBSD] |
80 | /// - [NetBSD] |
81 | /// - [OpenBSD] |
82 | /// - [DragonFly BSD] |
83 | /// - [illumos] |
84 | /// - [glibc] |
85 | /// |
86 | /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/pread.html |
87 | /// [Linux]: https://man7.org/linux/man-pages/man2/pread.2.html |
88 | /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/pread.2.html |
89 | /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=pread&sektion=2 |
90 | /// [NetBSD]: https://man.netbsd.org/pread.2 |
91 | /// [OpenBSD]: https://man.openbsd.org/pread.2 |
92 | /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=pread§ion=2 |
93 | /// [illumos]: https://illumos.org/man/2/pread |
94 | /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/I_002fO-Primitives.html#index-pread64 |
95 | #[cfg (not(windows))] |
96 | #[inline ] |
97 | pub fn pread<Fd: AsFd, Buf: Buffer<u8>>( |
98 | fd: Fd, |
99 | mut buf: Buf, |
100 | offset: u64, |
101 | ) -> io::Result<Buf::Output> { |
102 | // SAFETY: `pread` behaves. |
103 | let len: usize = unsafe { backend::io::syscalls::pread(fd.as_fd(), buf.parts_mut(), pos:offset)? }; |
104 | // SAFETY: `pread` behaves. |
105 | unsafe { Ok(buf.assume_init(len)) } |
106 | } |
107 | |
108 | /// `pwrite(fd, bufs)`—Writes to a file at a given position. |
109 | /// |
110 | /// Contrary to POSIX, on many popular platforms including Linux and FreeBSD, |
111 | /// if the file is opened in append mode, this ignores the offset appends the |
112 | /// data to the end of the file. |
113 | /// |
114 | /// # References |
115 | /// - [POSIX] |
116 | /// - [Linux] |
117 | /// - [Apple] |
118 | /// - [FreeBSD] |
119 | /// - [NetBSD] |
120 | /// - [OpenBSD] |
121 | /// - [DragonFly BSD] |
122 | /// - [illumos] |
123 | /// - [glibc] |
124 | /// |
125 | /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/pwrite.html |
126 | /// [Linux]: https://man7.org/linux/man-pages/man2/pwrite.2.html |
127 | /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/pwrite.2.html |
128 | /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=pwrite&sektion=2 |
129 | /// [NetBSD]: https://man.netbsd.org/pwrite.2 |
130 | /// [OpenBSD]: https://man.openbsd.org/pwrite.2 |
131 | /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=pwrite§ion=2 |
132 | /// [illumos]: https://illumos.org/man/2/pwrite |
133 | /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/I_002fO-Primitives.html#index-pwrite64 |
134 | #[cfg (not(windows))] |
135 | #[inline ] |
136 | pub fn pwrite<Fd: AsFd>(fd: Fd, buf: &[u8], offset: u64) -> io::Result<usize> { |
137 | backend::io::syscalls::pwrite(fd.as_fd(), buf, pos:offset) |
138 | } |
139 | |
140 | /// `readv(fd, bufs)`—Reads from a stream into multiple buffers. |
141 | /// |
142 | /// # References |
143 | /// - [POSIX] |
144 | /// - [Linux] |
145 | /// - [Apple] |
146 | /// - [FreeBSD] |
147 | /// - [NetBSD] |
148 | /// - [OpenBSD] |
149 | /// - [DragonFly BSD] |
150 | /// - [illumos] |
151 | /// - [glibc] |
152 | /// |
153 | /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/readv.html |
154 | /// [Linux]: https://man7.org/linux/man-pages/man2/readv.2.html |
155 | /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/readv.2.html |
156 | /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=readv&sektion=2 |
157 | /// [NetBSD]: https://man.netbsd.org/readv.2 |
158 | /// [OpenBSD]: https://man.openbsd.org/readv.2 |
159 | /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=readv§ion=2 |
160 | /// [illumos]: https://illumos.org/man/2/readv |
161 | /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Scatter_002dGather.html#index-readv |
162 | #[cfg (not(any(windows, target_os = "espidf" , target_os = "horizon" )))] |
163 | #[inline ] |
164 | pub fn readv<Fd: AsFd>(fd: Fd, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { |
165 | backend::io::syscalls::readv(fd.as_fd(), bufs) |
166 | } |
167 | |
168 | /// `writev(fd, bufs)`—Writes to a stream from multiple buffers. |
169 | /// |
170 | /// # References |
171 | /// - [POSIX] |
172 | /// - [Linux] |
173 | /// - [Apple] |
174 | /// - [FreeBSD] |
175 | /// - [NetBSD] |
176 | /// - [OpenBSD] |
177 | /// - [DragonFly BSD] |
178 | /// - [illumos] |
179 | /// - [glibc] |
180 | /// |
181 | /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/writev.html |
182 | /// [Linux]: https://man7.org/linux/man-pages/man2/writev.2.html |
183 | /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/writev.2.html |
184 | /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=writev&sektion=2 |
185 | /// [NetBSD]: https://man.netbsd.org/writev.2 |
186 | /// [OpenBSD]: https://man.openbsd.org/writev.2 |
187 | /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=writev§ion=2 |
188 | /// [illumos]: https://illumos.org/man/2/writev |
189 | /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Scatter_002dGather.html#index-writev |
190 | #[cfg (not(any(windows, target_os = "espidf" , target_os = "horizon" )))] |
191 | #[inline ] |
192 | pub fn writev<Fd: AsFd>(fd: Fd, bufs: &[IoSlice<'_>]) -> io::Result<usize> { |
193 | backend::io::syscalls::writev(fd.as_fd(), bufs) |
194 | } |
195 | |
196 | /// `preadv(fd, bufs, offset)`—Reads from a file at a given position into |
197 | /// multiple buffers. |
198 | /// |
199 | /// # References |
200 | /// - [Linux] |
201 | /// - [FreeBSD] |
202 | /// - [NetBSD] |
203 | /// - [OpenBSD] |
204 | /// - [DragonFly BSD] |
205 | /// - [illumos] |
206 | /// - [glibc] |
207 | /// |
208 | /// [Linux]: https://man7.org/linux/man-pages/man2/preadv.2.html |
209 | /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=preadv&sektion=2 |
210 | /// [NetBSD]: https://man.netbsd.org/preadv.2 |
211 | /// [OpenBSD]: https://man.openbsd.org/preadv.2 |
212 | /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=preadv§ion=2 |
213 | /// [illumos]: https://illumos.org/man/2/preadv |
214 | /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Scatter_002dGather.html#index-preadv64 |
215 | #[cfg (not(any( |
216 | windows, |
217 | target_os = "cygwin" , |
218 | target_os = "espidf" , |
219 | target_os = "haiku" , |
220 | target_os = "horizon" , |
221 | target_os = "nto" , |
222 | target_os = "redox" , |
223 | target_os = "solaris" , |
224 | target_os = "vita" , |
225 | )))] |
226 | #[inline ] |
227 | pub fn preadv<Fd: AsFd>(fd: Fd, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> { |
228 | backend::io::syscalls::preadv(fd.as_fd(), bufs, pos:offset) |
229 | } |
230 | |
231 | /// `pwritev(fd, bufs, offset)`—Writes to a file at a given position from |
232 | /// multiple buffers. |
233 | /// |
234 | /// Contrary to POSIX, on many popular platforms including Linux and FreeBSD, |
235 | /// if the file is opened in append mode, this ignores the offset appends the |
236 | /// data to the end of the file. |
237 | /// |
238 | /// # References |
239 | /// - [Linux] |
240 | /// - [FreeBSD] |
241 | /// - [NetBSD] |
242 | /// - [OpenBSD] |
243 | /// - [DragonFly BSD] |
244 | /// - [illumos] |
245 | /// - [glibc] |
246 | /// |
247 | /// [Linux]: https://man7.org/linux/man-pages/man2/pwritev.2.html |
248 | /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=pwritev&sektion=2 |
249 | /// [NetBSD]: https://man.netbsd.org/pwritev.2 |
250 | /// [OpenBSD]: https://man.openbsd.org/pwritev.2 |
251 | /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=pwritev§ion=2 |
252 | /// [illumos]: https://illumos.org/man/2/pwritev |
253 | /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/I_002fO-Primitives.html#index-pwrite64 |
254 | #[cfg (not(any( |
255 | windows, |
256 | target_os = "cygwin" , |
257 | target_os = "espidf" , |
258 | target_os = "haiku" , |
259 | target_os = "horizon" , |
260 | target_os = "nto" , |
261 | target_os = "redox" , |
262 | target_os = "solaris" , |
263 | target_os = "vita" , |
264 | )))] |
265 | #[inline ] |
266 | pub fn pwritev<Fd: AsFd>(fd: Fd, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> { |
267 | backend::io::syscalls::pwritev(fd.as_fd(), bufs, pos:offset) |
268 | } |
269 | |
270 | /// `preadv2(fd, bufs, offset, flags)`—Reads data, with several options. |
271 | /// |
272 | /// An `offset` of `u64::MAX` means to use and update the current file offset. |
273 | /// |
274 | /// # References |
275 | /// - [Linux] |
276 | /// - [glibc] |
277 | /// |
278 | /// [Linux]: https://man7.org/linux/man-pages/man2/preadv2.2.html |
279 | /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Scatter_002dGather.html#index-preadv64v2 |
280 | #[cfg (linux_kernel)] |
281 | #[inline ] |
282 | pub fn preadv2<Fd: AsFd>( |
283 | fd: Fd, |
284 | bufs: &mut [IoSliceMut<'_>], |
285 | offset: u64, |
286 | flags: ReadWriteFlags, |
287 | ) -> io::Result<usize> { |
288 | backend::io::syscalls::preadv2(fd.as_fd(), bufs, pos:offset, flags) |
289 | } |
290 | |
291 | /// `pwritev2(fd, bufs, offset, flags)`—Writes data, with several options. |
292 | /// |
293 | /// An `offset` of `u64::MAX` means to use and update the current file offset. |
294 | /// |
295 | /// # References |
296 | /// - [Linux] |
297 | /// - [glibc] |
298 | /// |
299 | /// [Linux]: https://man7.org/linux/man-pages/man2/pwritev2.2.html |
300 | /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Scatter_002dGather.html#index-pwritev64v2 |
301 | #[cfg (linux_kernel)] |
302 | #[inline ] |
303 | pub fn pwritev2<Fd: AsFd>( |
304 | fd: Fd, |
305 | bufs: &[IoSlice<'_>], |
306 | offset: u64, |
307 | flags: ReadWriteFlags, |
308 | ) -> io::Result<usize> { |
309 | backend::io::syscalls::pwritev2(fd.as_fd(), bufs, pos:offset, flags) |
310 | } |
311 | |