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