-
Notifications
You must be signed in to change notification settings - Fork 662
Expand file tree
/
Copy pathunix.rs
More file actions
73 lines (67 loc) · 2.27 KB
/
unix.rs
File metadata and controls
73 lines (67 loc) · 2.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
use std::ffi::c_int;
use std::io;
use std::ptr::{self, NonNull, null_mut};
/// Reserves a virtual memory region of the given size.
/// To commit the memory, use `virtual_commit`.
/// To release the memory, use `virtual_release`.
///
/// # Safety
///
/// This function is unsafe because it uses raw pointers.
/// Don't forget to release the memory when you're done with it or you'll leak it.
pub unsafe fn virtual_reserve(size: usize) -> io::Result<NonNull<u8>> {
unsafe {
let ptr = libc::mmap(
null_mut(),
size,
desired_mprotect(libc::PROT_READ | libc::PROT_WRITE),
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
-1,
0,
);
if ptr.is_null() || ptr::eq(ptr, libc::MAP_FAILED) {
Err(io::Error::last_os_error())
} else {
Ok(NonNull::new_unchecked(ptr.cast()))
}
}
}
#[cfg(target_os = "netbsd")]
const fn desired_mprotect(flags: c_int) -> c_int {
// NetBSD allows an mmap(2) caller to specify what protection flags they
// will use later via mprotect. It does not allow a caller to move from
// PROT_NONE to PROT_READ | PROT_WRITE.
//
// see PROT_MPROTECT in man 2 mmap
flags << 3
}
#[cfg(not(target_os = "netbsd"))]
const fn desired_mprotect(_: c_int) -> c_int {
libc::PROT_NONE
}
/// Releases a virtual memory region of the given size.
///
/// # Safety
///
/// This function is unsafe because it uses raw pointers.
/// Make sure to only pass pointers acquired from `virtual_reserve`.
pub unsafe fn virtual_release(base: NonNull<u8>, size: usize) {
unsafe {
libc::munmap(base.cast().as_ptr(), size);
}
}
/// Commits a virtual memory region of the given size.
///
/// # Safety
///
/// This function is unsafe because it uses raw pointers.
/// Make sure to only pass pointers acquired from `virtual_reserve`
/// and to pass a size less than or equal to the size passed to `virtual_reserve`.
pub unsafe fn virtual_commit(base: NonNull<u8>, size: usize) -> io::Result<()> {
unsafe {
let status = libc::mprotect(base.cast().as_ptr(), size, libc::PROT_READ | libc::PROT_WRITE);
if status != 0 { Err(io::Error::last_os_error()) } else { Ok(()) }
}
}