rustix/fs/special.rs
1//! The `CWD` and `ABS` constants, representing the current working directory
2//! and absolute-only paths, respectively.
3//!
4//! # Safety
5//!
6//! This file uses `AT_FDCWD`, which is a raw file descriptor, but which is
7//! always valid, and `-EBADF`, which is an undocumented by commonly used
8//! convention of passing a value which will always fail if the accompanying
9//! path isn't absolute.
10
11#![allow(unsafe_code)]
12
13use crate::backend;
14use backend::c;
15use backend::fd::{BorrowedFd, RawFd};
16
17/// `AT_FDCWD`—A handle representing the current working directory.
18///
19/// This is a file descriptor which refers to the process current directory
20/// which can be used as the directory argument in `*at` functions such as
21/// [`openat`].
22///
23/// # References
24/// - [POSIX]
25///
26/// [`openat`]: crate::fs::openat
27/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/fcntl.h.html
28// SAFETY: `AT_FDCWD` is a reserved value that is never dynamically
29// allocated, so it'll remain valid for the duration of `'static`.
30#[doc(alias = "AT_FDCWD")]
31pub const CWD: BorrowedFd<'static> =
32 unsafe { BorrowedFd::<'static>::borrow_raw(c::AT_FDCWD as RawFd) };
33
34/// `-EBADF`—A handle that requires paths to be absolute.
35///
36/// This is a file descriptor which refers to no directory, which can be used
37/// as the directory argument in `*at` functions such as [`openat`], which
38/// causes them to fail with [`BADF`] if the accompanying path is not absolute.
39///
40/// This corresponds to the undocumented by commonly used convention of
41/// passing `-EBADF` as the `dirfd` argument, which is ignored if the path
42/// is absolute, and evokes an `EBADF` error otherwise.
43///
44/// [`openat`]: crate::fs::openat
45/// [`BADF`]: crate::io::Errno::BADF
46// SAFETY: This `-EBADF` convention is commonly used, such as in lxc, so OS's
47// aren't going to break it.
48pub const ABS: BorrowedFd<'static> =
49 unsafe { BorrowedFd::<'static>::borrow_raw(c::EBADF.wrapping_neg() as RawFd) };
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54 use crate::fd::AsRawFd;
55
56 #[test]
57 fn test_cwd() {
58 assert!(CWD.as_raw_fd() != -1);
59 #[cfg(linux_kernel)]
60 #[cfg(feature = "io_uring")]
61 assert!(CWD.as_raw_fd() != linux_raw_sys::io_uring::IORING_REGISTER_FILES_SKIP);
62 }
63
64 #[test]
65 fn test_abs() {
66 assert!(ABS.as_raw_fd() < 0);
67 assert!(ABS.as_raw_fd() != -1);
68 assert!(ABS.as_raw_fd() != c::AT_FDCWD);
69 #[cfg(linux_kernel)]
70 #[cfg(feature = "io_uring")]
71 assert!(ABS.as_raw_fd() != linux_raw_sys::io_uring::IORING_REGISTER_FILES_SKIP);
72 }
73}