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
memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<OwnedFd>87 pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<OwnedFd> {
88     let res = 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                     //
97                     // ANDROID: Our glibc is too old to have memfd_create.
98                     // target_env = "gnu",
99                     target_env = "musl",
100                 )))]
101             {
102                 libc::memfd_create(name.as_ptr(), flags.bits())
103             } else {
104                 libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags.bits())
105             }
106         }
107     };
108 
109     Errno::result(res).map(|r| unsafe { OwnedFd::from_raw_fd(r as RawFd) })
110 }
111