rustix/
stdio.rs

1//! Functions returning the stdio file descriptors.
2//!
3//! # Safety
4//!
5//! These access the file descriptors by absolute index value, and nothing
6//! prevents them from being closed and reused. They should only be used in
7//! `main` or other situations where one is in control of the process' stdio
8//! streams.
9#![allow(unsafe_code)]
10
11use crate::backend;
12use crate::fd::OwnedFd;
13use backend::c;
14use backend::fd::{BorrowedFd, FromRawFd, RawFd};
15
16#[cfg(not(any(windows, target_os = "wasi")))]
17use {
18    crate::io,
19    backend::fd::{AsFd, AsRawFd},
20    core::mem::ManuallyDrop,
21};
22
23/// `STDIN_FILENO`—Standard input, borrowed.
24///
25/// In `std`-using configurations, this is a safe function, because the
26/// standard library already assumes that the stdin file descriptor is always
27/// valid. In `no_std` configurations, it is `unsafe`.
28///
29/// # Warning
30///
31/// This function allows reading directly from stdin without coordinating
32/// with the buffering performed by [`std::io::Stdin`], so it could cause
33/// corrupted input.
34///
35/// # References
36///  - [POSIX]
37///  - [Linux]
38///  - [FreeBSD]
39///  - [NetBSD]
40///  - [OpenBSD]
41///  - [DragonFly BSD]
42///  - [illumos]
43///  - [glibc]
44///
45/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stdin.html
46/// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html
47/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdin&sektion=4
48/// [NetBSD]: https://man.netbsd.org/stdin.4
49/// [OpenBSD]: https://man.openbsd.org/stdin.4
50/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdin&section=4
51/// [illumos]: https://illumos.org/man/4FS/stdin
52/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stdin
53#[cfg(feature = "std")]
54#[doc(alias = "STDIN_FILENO")]
55#[inline]
56pub const fn stdin() -> BorrowedFd<'static> {
57    // SAFETY: When "std" is enabled, the standard library assumes that the
58    // stdio file descriptors are all valid.
59    unsafe { BorrowedFd::borrow_raw(c::STDIN_FILENO as RawFd) }
60}
61
62/// `STDIN_FILENO`—Standard input, borrowed.
63///
64/// In `std`-using configurations, this is a safe function, because the
65/// standard library already assumes that the stdin file descriptor is always
66/// valid. In `no_std` configurations, it is `unsafe`.
67///
68/// # Safety
69///
70/// In `no_std` configurations, the stdin file descriptor can be closed,
71/// potentially on other threads, in which case the file descriptor index
72/// value could be dynamically reused for other purposes, potentially on
73/// different threads.
74///
75/// # Warning
76///
77/// This function allows reading directly from stdin without coordinating
78/// with the buffering performed by [`std::io::Stdin`], so it could cause
79/// corrupted input.
80///
81/// # References
82///  - [POSIX]
83///  - [Linux]
84///  - [FreeBSD]
85///  - [NetBSD]
86///  - [OpenBSD]
87///  - [DragonFly BSD]
88///  - [illumos]
89///  - [glibc]
90///
91/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stdin.html
92/// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html
93/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdin&sektion=4
94/// [NetBSD]: https://man.netbsd.org/stdin.4
95/// [OpenBSD]: https://man.openbsd.org/stdin.4
96/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdin&section=4
97/// [illumos]: https://illumos.org/man/4FS/stdin
98/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stdin
99#[cfg(not(feature = "std"))]
100#[doc(alias = "STDIN_FILENO")]
101#[inline]
102pub const unsafe fn stdin() -> BorrowedFd<'static> {
103    BorrowedFd::borrow_raw(c::STDIN_FILENO as RawFd)
104}
105
106/// `STDIN_FILENO`—Standard input, owned.
107///
108/// This is similar to [`stdin`], however it returns an `OwnedFd` which closes
109/// standard input when it is dropped.
110///
111/// # Safety
112///
113/// Safe `std`-using Rust code is permitted to assume that the stdin file
114/// descriptor is always valid. This function returns an `OwnedFd` which will
115/// close the stdin file descriptor when dropped.
116///
117/// # Warning
118///
119/// This has the same hazards as [`stdin`].
120///
121/// # References
122///  - [POSIX]
123///  - [Linux]
124///  - [FreeBSD]
125///  - [NetBSD]
126///  - [OpenBSD]
127///  - [DragonFly BSD]
128///  - [illumos]
129///  - [glibc]
130///
131/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stdin.html
132/// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html
133/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdin&sektion=4
134/// [NetBSD]: https://man.netbsd.org/stdin.4
135/// [OpenBSD]: https://man.openbsd.org/stdin.4
136/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdin&section=4
137/// [illumos]: https://illumos.org/man/4FS/stdin
138/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stdin
139#[doc(alias = "STDIN_FILENO")]
140#[inline]
141pub unsafe fn take_stdin() -> OwnedFd {
142    backend::fd::OwnedFd::from_raw_fd(c::STDIN_FILENO as RawFd)
143}
144
145/// `STDOUT_FILENO`—Standard output, borrowed.
146///
147/// In `std`-using configurations, this is a safe function, because the
148/// standard library already assumes that the stdout file descriptor is always
149/// valid. In `no_std` configurations, it is `unsafe`.
150///
151/// # Warning
152///
153/// This function allows writing directly to stdout without coordinating
154/// with the buffering performed by [`std::io::Stdout`], so it could cause
155/// corrupted output.
156///
157/// # References
158///  - [POSIX]
159///  - [Linux]
160///  - [FreeBSD]
161///  - [NetBSD]
162///  - [OpenBSD]
163///  - [DragonFly BSD]
164///  - [illumos]
165///  - [glibc]
166///
167/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stdout.html
168/// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html
169/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdout&sektion=4
170/// [NetBSD]: https://man.netbsd.org/stdout.4
171/// [OpenBSD]: https://man.openbsd.org/stdout.4
172/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdout&section=4
173/// [illumos]: https://illumos.org/man/4FS/stdout
174/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stdout
175#[cfg(feature = "std")]
176#[doc(alias = "STDOUT_FILENO")]
177#[inline]
178pub const fn stdout() -> BorrowedFd<'static> {
179    // SAFETY: When "std" is enabled, the standard library assumes that the
180    // stdio file descriptors are all valid.
181    unsafe { BorrowedFd::borrow_raw(c::STDOUT_FILENO as RawFd) }
182}
183
184/// `STDOUT_FILENO`—Standard output, borrowed.
185///
186/// In `std`-using configurations, this is a safe function, because the
187/// standard library already assumes that the stdout file descriptor is always
188/// valid. In `no_std` configurations, it is `unsafe`.
189///
190/// # Safety
191///
192/// In `no_std` configurations, the stdout file descriptor can be closed,
193/// potentially on other threads, in which case the file descriptor index
194/// value could be dynamically reused for other purposes, potentially on
195/// different threads.
196///
197/// # Warning
198///
199/// This function allows writing directly to stdout without coordinating
200/// with the buffering performed by [`std::io::Stdout`], so it could cause
201/// corrupted output.
202///
203/// # References
204///  - [POSIX]
205///  - [Linux]
206///  - [FreeBSD]
207///  - [NetBSD]
208///  - [OpenBSD]
209///  - [DragonFly BSD]
210///  - [illumos]
211///  - [glibc]
212///
213/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stdout.html
214/// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html
215/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdout&sektion=4
216/// [NetBSD]: https://man.netbsd.org/stdout.4
217/// [OpenBSD]: https://man.openbsd.org/stdout.4
218/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdout&section=4
219/// [illumos]: https://illumos.org/man/4FS/stdout
220/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stdout
221#[cfg(not(feature = "std"))]
222#[doc(alias = "STDOUT_FILENO")]
223#[inline]
224pub const unsafe fn stdout() -> BorrowedFd<'static> {
225    BorrowedFd::borrow_raw(c::STDOUT_FILENO as RawFd)
226}
227
228/// `STDOUT_FILENO`—Standard output, owned.
229///
230/// This is similar to [`stdout`], however it returns an `OwnedFd` which closes
231/// standard output when it is dropped.
232///
233/// # Safety
234///
235/// Safe `std`-using Rust code is permitted to assume that the stdout file
236/// descriptor is always valid. This function returns an `OwnedFd` which will
237/// close the stdout file descriptor when dropped.
238///
239/// # Warning
240///
241/// This has the same hazards as [`stdout`].
242///
243/// # References
244///  - [POSIX]
245///  - [Linux]
246///  - [FreeBSD]
247///  - [NetBSD]
248///  - [OpenBSD]
249///  - [DragonFly BSD]
250///  - [illumos]
251///  - [glibc]
252///
253/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stdout.html
254/// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html
255/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdout&sektion=4
256/// [NetBSD]: https://man.netbsd.org/stdout.4
257/// [OpenBSD]: https://man.openbsd.org/stdout.4
258/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdout&section=4
259/// [illumos]: https://illumos.org/man/4FS/stdout
260/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stdout
261#[doc(alias = "STDOUT_FILENO")]
262#[inline]
263pub unsafe fn take_stdout() -> OwnedFd {
264    backend::fd::OwnedFd::from_raw_fd(c::STDOUT_FILENO as RawFd)
265}
266
267/// `STDERR_FILENO`—Standard error, borrowed.
268///
269/// In `std`-using configurations, this is a safe function, because the
270/// standard library already assumes that the stderr file descriptor is always
271/// valid. In `no_std` configurations, it is `unsafe`.
272///
273/// # References
274///  - [POSIX]
275///  - [Linux]
276///  - [FreeBSD]
277///  - [NetBSD]
278///  - [OpenBSD]
279///  - [DragonFly BSD]
280///  - [illumos]
281///  - [glibc]
282///
283/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stderr.html
284/// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html
285/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stderr&sektion=4
286/// [NetBSD]: https://man.netbsd.org/stderr.4
287/// [OpenBSD]: https://man.openbsd.org/stderr.4
288/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stderr&section=4
289/// [illumos]: https://illumos.org/man/4FS/stderr
290/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stderr
291#[cfg(feature = "std")]
292#[doc(alias = "STDERR_FILENO")]
293#[inline]
294pub const fn stderr() -> BorrowedFd<'static> {
295    // SAFETY: When "std" is enabled, the standard library assumes that the
296    // stdio file descriptors are all valid.
297    unsafe { BorrowedFd::borrow_raw(c::STDERR_FILENO as RawFd) }
298}
299
300/// `STDERR_FILENO`—Standard error, borrowed.
301///
302/// In `std`-using configurations, this is a safe function, because the
303/// standard library already assumes that the stderr file descriptor is always
304/// valid. In `no_std` configurations, it is `unsafe`.
305///
306/// # Safety
307///
308/// In `no_std` configurations, the stderr file descriptor can be closed,
309/// potentially on other threads, in which case the file descriptor index
310/// value could be dynamically reused for other purposes, potentially on
311/// different threads.
312///
313/// # References
314///  - [POSIX]
315///  - [Linux]
316///  - [FreeBSD]
317///  - [NetBSD]
318///  - [OpenBSD]
319///  - [DragonFly BSD]
320///  - [illumos]
321///  - [glibc]
322///
323/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stderr.html
324/// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html
325/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stderr&sektion=4
326/// [NetBSD]: https://man.netbsd.org/stderr.4
327/// [OpenBSD]: https://man.openbsd.org/stderr.4
328/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stderr&section=4
329/// [illumos]: https://illumos.org/man/4FS/stderr
330/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stderr
331#[cfg(not(feature = "std"))]
332#[doc(alias = "STDERR_FILENO")]
333#[inline]
334pub const unsafe fn stderr() -> BorrowedFd<'static> {
335    BorrowedFd::borrow_raw(c::STDERR_FILENO as RawFd)
336}
337
338/// `STDERR_FILENO`—Standard error, owned.
339///
340/// This is similar to [`stderr`], however it returns an `OwnedFd` which closes
341/// standard output when it is dropped.
342///
343/// # Safety
344///
345/// Safe std-using Rust code is permitted to assume that the stderr file
346/// descriptor is always valid. This function returns an `OwnedFd` which will
347/// close the stderr file descriptor when dropped.
348///
349/// # Other hazards
350///
351/// This has the same hazards as [`stderr`].
352///
353/// And, when the `OwnedFd` is dropped, subsequent newly created file
354/// descriptors may unknowingly reuse the stderr file descriptor number, which
355/// may break common assumptions, so it should typically only be dropped at the
356/// end of a program when no more file descriptors will be created.
357///
358/// # References
359///  - [POSIX]
360///  - [Linux]
361///  - [FreeBSD]
362///  - [NetBSD]
363///  - [OpenBSD]
364///  - [DragonFly BSD]
365///  - [illumos]
366///  - [glibc]
367///
368/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stderr.html
369/// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html
370/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stderr&sektion=4
371/// [NetBSD]: https://man.netbsd.org/stderr.4
372/// [OpenBSD]: https://man.openbsd.org/stderr.4
373/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stderr&section=4
374/// [illumos]: https://illumos.org/man/4FS/stderr
375/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stderr
376#[doc(alias = "STDERR_FILENO")]
377#[inline]
378pub unsafe fn take_stderr() -> OwnedFd {
379    backend::fd::OwnedFd::from_raw_fd(c::STDERR_FILENO as RawFd)
380}
381
382/// `STDIN_FILENO`—Standard input, raw.
383///
384/// This is similar to [`stdin`], however it returns a `RawFd`.
385///
386/// # Other hazards
387///
388/// This has the same hazards as [`stdin`].
389///
390/// # References
391///  - [POSIX]
392///  - [Linux]
393///  - [FreeBSD]
394///  - [NetBSD]
395///  - [OpenBSD]
396///  - [DragonFly BSD]
397///  - [illumos]
398///  - [glibc]
399///
400/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stdin.html
401/// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html
402/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdin&sektion=4
403/// [NetBSD]: https://man.netbsd.org/stdin.4
404/// [OpenBSD]: https://man.openbsd.org/stdin.4
405/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdin&section=4
406/// [illumos]: https://illumos.org/man/4FS/stdin
407/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stdin
408#[doc(alias = "STDIN_FILENO")]
409#[inline]
410pub const fn raw_stdin() -> RawFd {
411    c::STDIN_FILENO as RawFd
412}
413
414/// `STDOUT_FILENO`—Standard output, raw.
415///
416/// This is similar to [`stdout`], however it returns a `RawFd`.
417///
418/// # Other hazards
419///
420/// This has the same hazards as [`stdout`].
421///
422/// # References
423///  - [POSIX]
424///  - [Linux]
425///  - [FreeBSD]
426///  - [NetBSD]
427///  - [OpenBSD]
428///  - [DragonFly BSD]
429///  - [illumos]
430///  - [glibc]
431///
432/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stdout.html
433/// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html
434/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdout&sektion=4
435/// [NetBSD]: https://man.netbsd.org/stdout.4
436/// [OpenBSD]: https://man.openbsd.org/stdout.4
437/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdout&section=4
438/// [illumos]: https://illumos.org/man/4FS/stdout
439/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stdout
440#[doc(alias = "STDOUT_FILENO")]
441#[inline]
442pub const fn raw_stdout() -> RawFd {
443    c::STDOUT_FILENO as RawFd
444}
445
446/// `STDERR_FILENO`—Standard error, raw.
447///
448/// This is similar to [`stderr`], however it returns a `RawFd`.
449///
450/// # Other hazards
451///
452/// This has the same hazards as [`stderr`].
453///
454/// # References
455///  - [POSIX]
456///  - [Linux]
457///  - [FreeBSD]
458///  - [NetBSD]
459///  - [OpenBSD]
460///  - [DragonFly BSD]
461///  - [illumos]
462///  - [glibc]
463///
464/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stderr.html
465/// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html
466/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stderr&sektion=4
467/// [NetBSD]: https://man.netbsd.org/stderr.4
468/// [OpenBSD]: https://man.openbsd.org/stderr.4
469/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stderr&section=4
470/// [illumos]: https://illumos.org/man/4FS/stderr
471/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stderr
472#[doc(alias = "STDERR_FILENO")]
473#[inline]
474pub const fn raw_stderr() -> RawFd {
475    c::STDERR_FILENO as RawFd
476}
477
478/// Utility function to safely `dup2` over stdin (fd 0).
479#[cfg(not(any(windows, target_os = "wasi")))]
480#[inline]
481pub fn dup2_stdin<Fd: AsFd>(fd: Fd) -> io::Result<()> {
482    let fd = fd.as_fd();
483    if fd.as_raw_fd() != c::STDIN_FILENO {
484        // SAFETY: We wrap the returned `OwnedFd` to `ManuallyDrop` so that it
485        // isn't dropped.
486        let mut target = ManuallyDrop::new(unsafe { take_stdin() });
487        backend::io::syscalls::dup2(fd, &mut target)?;
488    }
489    Ok(())
490}
491
492/// Utility function to safely `dup2` over stdout (fd 1).
493#[cfg(not(any(windows, target_os = "wasi")))]
494#[inline]
495pub fn dup2_stdout<Fd: AsFd>(fd: Fd) -> io::Result<()> {
496    let fd = fd.as_fd();
497    if fd.as_raw_fd() != c::STDOUT_FILENO {
498        // SAFETY: We wrap the returned `OwnedFd` to `ManuallyDrop` so that it
499        // isn't dropped.
500        let mut target = ManuallyDrop::new(unsafe { take_stdout() });
501        backend::io::syscalls::dup2(fd, &mut target)?;
502    }
503    Ok(())
504}
505
506/// Utility function to safely `dup2` over stderr (fd 2).
507#[cfg(not(any(windows, target_os = "wasi")))]
508#[inline]
509pub fn dup2_stderr<Fd: AsFd>(fd: Fd) -> io::Result<()> {
510    let fd = fd.as_fd();
511    if fd.as_raw_fd() != c::STDERR_FILENO {
512        // SAFETY: We wrap the returned `OwnedFd` to `ManuallyDrop` so that it
513        // isn't dropped.
514        let mut target = ManuallyDrop::new(unsafe { take_stderr() });
515        backend::io::syscalls::dup2(fd, &mut target)?;
516    }
517    Ok(())
518}