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 | } |
33 | ); |
34 | |
35 | /// Creates an anonymous file that lives in memory, and return a file-descriptor to it. |
36 | /// |
37 | /// The file behaves like a regular file, and so can be modified, truncated, memory-mapped, and so on. |
38 | /// However, unlike a regular file, it lives in RAM and has a volatile backing storage. |
39 | /// |
40 | /// For more information, see [`memfd_create(2)`]. |
41 | /// |
42 | /// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html |
43 | #[inline ] // Delays codegen, preventing linker errors with dylibs and --no-allow-shlib-undefined |
44 | pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<OwnedFd> { |
45 | let res: i32 = unsafe { |
46 | cfg_if! { |
47 | if #[cfg(all( |
48 | // Android does not have a memfd_create symbol |
49 | not(target_os = "android" ), |
50 | any( |
51 | target_os = "freebsd" , |
52 | // If the OS is Linux, gnu and musl expose a memfd_create symbol but not uclibc |
53 | target_env = "gnu" , |
54 | target_env = "musl" , |
55 | )))] |
56 | { |
57 | libc::memfd_create(name.as_ptr(), flags.bits()) |
58 | } else { |
59 | libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags.bits()) |
60 | } |
61 | } |
62 | }; |
63 | |
64 | Errno::result(res).map(|r: i32| unsafe { OwnedFd::from_raw_fd(r as RawFd) }) |
65 | } |
66 | |