rustix/io/read_write.rs
1//! `read` and `write`, optionally positioned, optionally vectored.
2
3#![allow(unsafe_code)]
4
5use crate::buffer::Buffer;
6use crate::{backend, io};
7use backend::fd::AsFd;
8
9// Declare `IoSlice` and `IoSliceMut`.
10#[cfg(not(windows))]
11pub use crate::maybe_polyfill::io::{IoSlice, IoSliceMut};
12
13#[cfg(linux_kernel)]
14pub 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]
39pub fn read<Fd: AsFd, Buf: Buffer<u8>>(fd: Fd, mut buf: Buf) -> io::Result<Buf::Output> {
40 // SAFETY: `read` behaves.
41 let len = 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]
69pub 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]
97pub 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 = unsafe { backend::io::syscalls::pread(fd.as_fd(), buf.parts_mut(), 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]
136pub fn pwrite<Fd: AsFd>(fd: Fd, buf: &[u8], offset: u64) -> io::Result<usize> {
137 backend::io::syscalls::pwrite(fd.as_fd(), buf, 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]
164pub 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]
192pub 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 = "espidf",
218 target_os = "haiku",
219 target_os = "horizon",
220 target_os = "nto",
221 target_os = "redox",
222 target_os = "solaris",
223 target_os = "vita"
224)))]
225#[inline]
226pub fn preadv<Fd: AsFd>(fd: Fd, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
227 backend::io::syscalls::preadv(fd.as_fd(), bufs, offset)
228}
229
230/// `pwritev(fd, bufs, offset)`—Writes to a file at a given position from
231/// multiple buffers.
232///
233/// Contrary to POSIX, on many popular platforms including Linux and FreeBSD,
234/// if the file is opened in append mode, this ignores the offset appends the
235/// data to the end of the file.
236///
237/// # References
238/// - [Linux]
239/// - [FreeBSD]
240/// - [NetBSD]
241/// - [OpenBSD]
242/// - [DragonFly BSD]
243/// - [illumos]
244/// - [glibc]
245///
246/// [Linux]: https://man7.org/linux/man-pages/man2/pwritev.2.html
247/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=pwritev&sektion=2
248/// [NetBSD]: https://man.netbsd.org/pwritev.2
249/// [OpenBSD]: https://man.openbsd.org/pwritev.2
250/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=pwritev§ion=2
251/// [illumos]: https://illumos.org/man/2/pwritev
252/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/I_002fO-Primitives.html#index-pwrite64
253#[cfg(not(any(
254 windows,
255 target_os = "espidf",
256 target_os = "haiku",
257 target_os = "horizon",
258 target_os = "nto",
259 target_os = "redox",
260 target_os = "solaris",
261 target_os = "vita"
262)))]
263#[inline]
264pub fn pwritev<Fd: AsFd>(fd: Fd, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
265 backend::io::syscalls::pwritev(fd.as_fd(), bufs, offset)
266}
267
268/// `preadv2(fd, bufs, offset, flags)`—Reads data, with several options.
269///
270/// An `offset` of `u64::MAX` means to use and update the current file offset.
271///
272/// # References
273/// - [Linux]
274/// - [glibc]
275///
276/// [Linux]: https://man7.org/linux/man-pages/man2/preadv2.2.html
277/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Scatter_002dGather.html#index-preadv64v2
278#[cfg(linux_kernel)]
279#[inline]
280pub fn preadv2<Fd: AsFd>(
281 fd: Fd,
282 bufs: &mut [IoSliceMut<'_>],
283 offset: u64,
284 flags: ReadWriteFlags,
285) -> io::Result<usize> {
286 backend::io::syscalls::preadv2(fd.as_fd(), bufs, offset, flags)
287}
288
289/// `pwritev2(fd, bufs, offset, flags)`—Writes data, with several options.
290///
291/// An `offset` of `u64::MAX` means to use and update the current file offset.
292///
293/// # References
294/// - [Linux]
295/// - [glibc]
296///
297/// [Linux]: https://man7.org/linux/man-pages/man2/pwritev2.2.html
298/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Scatter_002dGather.html#index-pwritev64v2
299#[cfg(linux_kernel)]
300#[inline]
301pub fn pwritev2<Fd: AsFd>(
302 fd: Fd,
303 bufs: &[IoSlice<'_>],
304 offset: u64,
305 flags: ReadWriteFlags,
306) -> io::Result<usize> {
307 backend::io::syscalls::pwritev2(fd.as_fd(), bufs, offset, flags)
308}