1 | //! Interfaces for managing memory-backed files. |
2 | |
3 | use cfg_if::cfg_if; |
4 | use std::os::unix::io::{FromRawFd, OwnedFd, RawFd}; |
5 | |
6 | use crate::errno::Errno; |
7 | use crate::Result; |
8 | use std::ffi::CStr; |
9 | |
10 | libc_bitflags!( |
11 | /// Options that change the behavior of [`memfd_create`]. |
12 | pub struct MemFdCreateFlag: libc::c_uint { |
13 | /// Set the close-on-exec ([`FD_CLOEXEC`]) flag on the new file descriptor. |
14 | /// |
15 | /// By default, the new file descriptor is set to remain open across an [`execve`] |
16 | /// (the `FD_CLOEXEC` flag is initially disabled). This flag can be used to change |
17 | /// this default. The file offset is set to the beginning of the file (see [`lseek`]). |
18 | /// |
19 | /// See also the description of the `O_CLOEXEC` flag in [`open(2)`]. |
20 | /// |
21 | /// [`execve`]: crate::unistd::execve |
22 | /// [`lseek`]: crate::unistd::lseek |
23 | /// [`FD_CLOEXEC`]: crate::fcntl::FdFlag::FD_CLOEXEC |
24 | /// [`open(2)`]: https://man7.org/linux/man-pages/man2/open.2.html |
25 | MFD_CLOEXEC; |
26 | /// Allow sealing operations on this file. |
27 | /// |
28 | /// See also the file sealing notes given in [`memfd_create(2)`]. |
29 | /// |
30 | /// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html |
31 | MFD_ALLOW_SEALING; |
32 | /// Anonymous file will be created using huge pages. It should be safe now to |
33 | /// combine with [`MFD_ALLOW_SEALING`] too. |
34 | /// However, despite its presence, on FreeBSD it is unimplemented for now (ENOSYS). |
35 | /// |
36 | /// See also the hugetlb filesystem in [`memfd_create(2)`]. |
37 | /// |
38 | /// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html |
39 | #[cfg (linux_android)] |
40 | MFD_HUGETLB; |
41 | /// Following are to be used with [`MFD_HUGETLB`], indicating the desired hugetlb size. |
42 | /// |
43 | /// See also the hugetlb filesystem in [`memfd_create(2)`]. |
44 | /// |
45 | /// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html |
46 | #[cfg (linux_android)] |
47 | MFD_HUGE_1MB; |
48 | /// hugetlb size of 2MB. |
49 | #[cfg (linux_android)] |
50 | MFD_HUGE_2MB; |
51 | /// hugetlb size of 8MB. |
52 | #[cfg (linux_android)] |
53 | MFD_HUGE_8MB; |
54 | /// hugetlb size of 16MB. |
55 | #[cfg (linux_android)] |
56 | MFD_HUGE_16MB; |
57 | /// hugetlb size of 32MB. |
58 | #[cfg (linux_android)] |
59 | MFD_HUGE_32MB; |
60 | /// hugetlb size of 256MB. |
61 | #[cfg (linux_android)] |
62 | MFD_HUGE_256MB; |
63 | /// hugetlb size of 512MB. |
64 | #[cfg (linux_android)] |
65 | MFD_HUGE_512MB; |
66 | /// hugetlb size of 1GB. |
67 | #[cfg (linux_android)] |
68 | MFD_HUGE_1GB; |
69 | /// hugetlb size of 2GB. |
70 | #[cfg (linux_android)] |
71 | MFD_HUGE_2GB; |
72 | /// hugetlb size of 16GB. |
73 | #[cfg (linux_android)] |
74 | MFD_HUGE_16GB; |
75 | } |
76 | ); |
77 | |
78 | /// Creates an anonymous file that lives in memory, and return a file-descriptor to it. |
79 | /// |
80 | /// The file behaves like a regular file, and so can be modified, truncated, memory-mapped, and so on. |
81 | /// However, unlike a regular file, it lives in RAM and has a volatile backing storage. |
82 | /// |
83 | /// For more information, see [`memfd_create(2)`]. |
84 | /// |
85 | /// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html |
86 | #[inline ] // Delays codegen, preventing linker errors with dylibs and --no-allow-shlib-undefined |
87 | pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<OwnedFd> { |
88 | let res: i32 = unsafe { |
89 | cfg_if! { |
90 | if #[cfg(all( |
91 | // Android does not have a memfd_create symbol |
92 | not(target_os = "android" ), |
93 | any( |
94 | target_os = "freebsd" , |
95 | // If the OS is Linux, gnu and musl expose a memfd_create symbol but not uclibc |
96 | target_env = "gnu" , |
97 | target_env = "musl" , |
98 | )))] |
99 | { |
100 | libc::memfd_create(name.as_ptr(), flags.bits()) |
101 | } else { |
102 | libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags.bits()) |
103 | } |
104 | } |
105 | }; |
106 | |
107 | Errno::result(res).map(|r: i32| unsafe { OwnedFd::from_raw_fd(r as RawFd) }) |
108 | } |
109 | |