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&section=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&section=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&section=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&section=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&section=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&section=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&section=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&section=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}