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§ion=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§ion=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§ion=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§ion=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§ion=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§ion=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§ion=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§ion=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§ion=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§ion=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§ion=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§ion=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}