1use nix::sys::mman::{mmap, MapFlags, ProtFlags};
2use std::num::NonZeroUsize;
3
4#[test]
5fn test_mmap_anonymous() {
6    unsafe {
7        let ptr = mmap(
8            None,
9            NonZeroUsize::new(1).unwrap(),
10            ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
11            MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS,
12            -1,
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(
33            None,
34            one_k_non_zero,
35            ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
36            MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE,
37            -1,
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(
91            None,
92            ten_one_k,
93            ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
94            MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE,
95            -1,
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