1use nix::sys::mman::{mmap, MapFlags, ProtFlags};
2use std::{num::NonZeroUsize, os::unix::io::BorrowedFd};
3
4#[test]
5fn test_mmap_anonymous() {
6 unsafe {
7 let ptr = mmap::<BorrowedFd>(
8 None,
9 NonZeroUsize::new(1).unwrap(),
10 ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
11 MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS,
12 None,
13 0,
14 )
15 .unwrap() as *mut u8;
16 assert_eq!(*ptr, 0x00u8);
17 *ptr = 0xffu8;
18 assert_eq!(*ptr, 0xffu8);
19 }
20}
21
22#[test]
23#[cfg(any(target_os = "linux", target_os = "netbsd"))]
24fn test_mremap_grow() {
25 use nix::libc::{c_void, size_t};
26 use nix::sys::mman::{mremap, MRemapFlags};
27
28 const ONE_K: size_t = 1024;
29 let one_k_non_zero = NonZeroUsize::new(ONE_K).unwrap();
30
31 let slice: &mut [u8] = unsafe {
32 let mem = mmap::<BorrowedFd>(
33 None,
34 one_k_non_zero,
35 ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
36 MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE,
37 None,
38 0,
39 )
40 .unwrap();
41 std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K)
42 };
43 assert_eq!(slice[ONE_K - 1], 0x00);
44 slice[ONE_K - 1] = 0xFF;
45 assert_eq!(slice[ONE_K - 1], 0xFF);
46
47 let slice: &mut [u8] = unsafe {
48 #[cfg(target_os = "linux")]
49 let mem = mremap(
50 slice.as_mut_ptr() as *mut c_void,
51 ONE_K,
52 10 * ONE_K,
53 MRemapFlags::MREMAP_MAYMOVE,
54 None,
55 )
56 .unwrap();
57 #[cfg(target_os = "netbsd")]
58 let mem = mremap(
59 slice.as_mut_ptr() as *mut c_void,
60 ONE_K,
61 10 * ONE_K,
62 MRemapFlags::MAP_REMAPDUP,
63 None,
64 )
65 .unwrap();
66 std::slice::from_raw_parts_mut(mem as *mut u8, 10 * ONE_K)
67 };
68
69 // The first KB should still have the old data in it.
70 assert_eq!(slice[ONE_K - 1], 0xFF);
71
72 // The additional range should be zero-init'd and accessible.
73 assert_eq!(slice[10 * ONE_K - 1], 0x00);
74 slice[10 * ONE_K - 1] = 0xFF;
75 assert_eq!(slice[10 * ONE_K - 1], 0xFF);
76}
77
78#[test]
79#[cfg(any(target_os = "linux", target_os = "netbsd"))]
80// Segfaults for unknown reasons under QEMU for 32-bit targets
81#[cfg_attr(all(target_pointer_width = "32", qemu), ignore)]
82fn test_mremap_shrink() {
83 use nix::libc::{c_void, size_t};
84 use nix::sys::mman::{mremap, MRemapFlags};
85 use std::num::NonZeroUsize;
86
87 const ONE_K: size_t = 1024;
88 let ten_one_k = NonZeroUsize::new(10 * ONE_K).unwrap();
89 let slice: &mut [u8] = unsafe {
90 let mem = mmap::<BorrowedFd>(
91 None,
92 ten_one_k,
93 ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
94 MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE,
95 None,
96 0,
97 )
98 .unwrap();
99 std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K)
100 };
101 assert_eq!(slice[ONE_K - 1], 0x00);
102 slice[ONE_K - 1] = 0xFF;
103 assert_eq!(slice[ONE_K - 1], 0xFF);
104
105 let slice: &mut [u8] = unsafe {
106 let mem = mremap(
107 slice.as_mut_ptr() as *mut c_void,
108 ten_one_k.into(),
109 ONE_K,
110 MRemapFlags::empty(),
111 None,
112 )
113 .unwrap();
114 // Since we didn't supply MREMAP_MAYMOVE, the address should be the
115 // same.
116 assert_eq!(mem, slice.as_mut_ptr() as *mut c_void);
117 std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K)
118 };
119
120 // The first KB should still be accessible and have the old data in it.
121 assert_eq!(slice[ONE_K - 1], 0xFF);
122}
123