use {Error, Result};
#[cfg(not(target_os = "android"))]
use NixPath;
use errno::Errno;
#[cfg(not(target_os = "android"))]
use fcntl::OFlag;
use libc::{self, c_int, c_void, size_t, off_t};
#[cfg(not(target_os = "android"))]
use sys::stat::Mode;
use std::os::unix::io::RawFd;
libc_bitflags!{
pub struct ProtFlags: c_int {
PROT_NONE;
PROT_READ;
PROT_WRITE;
PROT_EXEC;
#[cfg(any(target_os = "android", target_os = "linux"))]
PROT_GROWSDOWN;
#[cfg(any(target_os = "android", target_os = "linux"))]
PROT_GROWSUP;
}
}
libc_bitflags!{
pub struct MapFlags: c_int {
MAP_FILE;
MAP_SHARED;
MAP_PRIVATE;
MAP_FIXED;
MAP_ANON;
#[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))]
MAP_ANONYMOUS;
#[cfg(any(all(any(target_os = "android", target_os = "linux"),
any(target_arch = "x86", target_arch = "x86_64")),
all(target_os = "linux", target_env = "musl", any(target_arch = "x86", target_arch = "x86_64")),
all(target_os = "freebsd", target_pointer_width = "64")))]
MAP_32BIT;
#[cfg(any(target_os = "android", target_os = "linux"))]
MAP_GROWSDOWN;
#[cfg(any(target_os = "android", target_os = "linux"))]
MAP_DENYWRITE;
#[cfg(any(target_os = "android", target_os = "linux"))]
MAP_EXECUTABLE;
#[cfg(any(target_os = "android", target_os = "linux"))]
MAP_LOCKED;
#[cfg(not(target_os = "freebsd"))]
MAP_NORESERVE;
#[cfg(any(target_os = "android", target_os = "linux"))]
MAP_POPULATE;
#[cfg(any(target_os = "android", target_os = "linux"))]
MAP_NONBLOCK;
#[cfg(any(target_os = "android", target_os = "linux"))]
MAP_HUGETLB;
#[cfg(target_os = "netbsd")]
MAP_WIRED;
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
MAP_NOSYNC;
#[cfg(any(target_os = "dragonfly", target_os = "netbsd", target_os = "openbsd"))]
MAP_RENAME;
#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
MAP_HASSEMAPHORE;
#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
MAP_STACK;
#[cfg(any(target_os = "ios", target_os = "macos"))]
MAP_NOCACHE;
#[cfg(any(target_os = "ios", target_os = "macos"))]
MAP_JIT;
}
}
libc_enum!{
#[repr(i32)]
pub enum MmapAdvise {
MADV_NORMAL,
MADV_RANDOM,
MADV_SEQUENTIAL,
MADV_WILLNEED,
MADV_DONTNEED,
#[cfg(any(target_os = "android", target_os = "linux"))]
MADV_REMOVE,
#[cfg(any(target_os = "android", target_os = "linux"))]
MADV_DONTFORK,
#[cfg(any(target_os = "android", target_os = "linux"))]
MADV_DOFORK,
#[cfg(any(target_os = "android", target_os = "linux"))]
MADV_HWPOISON,
#[cfg(any(target_os = "android", target_os = "linux"))]
MADV_MERGEABLE,
#[cfg(any(target_os = "android", target_os = "linux"))]
MADV_UNMERGEABLE,
#[cfg(any(target_os = "android",
all(target_os = "linux", any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "ppc",
target_arch = "s390x",
target_arch = "x86",
target_arch = "x86_64",
target_arch = "sparc64"))))]
MADV_SOFT_OFFLINE,
#[cfg(any(target_os = "android", target_os = "linux"))]
MADV_HUGEPAGE,
#[cfg(any(target_os = "android", target_os = "linux"))]
MADV_NOHUGEPAGE,
#[cfg(any(target_os = "android", target_os = "linux"))]
MADV_DONTDUMP,
#[cfg(any(target_os = "android", target_os = "linux"))]
MADV_DODUMP,
MADV_FREE,
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
MADV_NOSYNC,
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
MADV_AUTOSYNC,
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
MADV_NOCORE,
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
MADV_CORE,
#[cfg(any(target_os = "freebsd"))]
MADV_PROTECT,
#[cfg(target_os = "dragonfly")]
MADV_INVAL,
#[cfg(target_os = "dragonfly")]
MADV_SETMAP,
#[cfg(any(target_os = "ios", target_os = "macos"))]
MADV_ZERO_WIRED_PAGES,
#[cfg(any(target_os = "ios", target_os = "macos"))]
MADV_FREE_REUSABLE,
#[cfg(any(target_os = "ios", target_os = "macos"))]
MADV_FREE_REUSE,
#[cfg(any(target_os = "ios", target_os = "macos"))]
MADV_CAN_REUSE,
}
}
libc_bitflags!{
pub struct MsFlags: c_int {
MS_ASYNC;
MS_INVALIDATE;
#[cfg(any(target_os = "ios", target_os = "macos"))]
MS_KILLPAGES;
#[cfg(any(target_os = "ios", target_os = "macos"))]
MS_DEACTIVATE;
MS_SYNC;
}
}
libc_bitflags!{
pub struct MlockAllFlags: c_int {
MCL_CURRENT;
MCL_FUTURE;
}
}
pub unsafe fn mlock(addr: *const c_void, length: size_t) -> Result<()> {
Errno::result(libc::mlock(addr, length)).map(drop)
}
pub unsafe fn munlock(addr: *const c_void, length: size_t) -> Result<()> {
Errno::result(libc::munlock(addr, length)).map(drop)
}
pub fn mlockall(flags: MlockAllFlags) -> Result<()> {
unsafe { Errno::result(libc::mlockall(flags.bits())) }.map(drop)
}
pub fn munlockall() -> Result<()> {
unsafe { Errno::result(libc::munlockall()) }.map(drop)
}
pub unsafe fn mmap(addr: *mut c_void, length: size_t, prot: ProtFlags, flags: MapFlags, fd: RawFd, offset: off_t) -> Result<*mut c_void> {
let ret = libc::mmap(addr, length, prot.bits(), flags.bits(), fd, offset);
if ret == libc::MAP_FAILED {
Err(Error::Sys(Errno::last()))
} else {
Ok(ret)
}
}
pub unsafe fn munmap(addr: *mut c_void, len: size_t) -> Result<()> {
Errno::result(libc::munmap(addr, len)).map(drop)
}
pub unsafe fn madvise(addr: *mut c_void, length: size_t, advise: MmapAdvise) -> Result<()> {
Errno::result(libc::madvise(addr, length, advise as i32)).map(drop)
}
pub unsafe fn msync(addr: *mut c_void, length: size_t, flags: MsFlags) -> Result<()> {
Errno::result(libc::msync(addr, length, flags.bits())).map(drop)
}
#[cfg(not(target_os = "android"))]
pub fn shm_open<P: ?Sized + NixPath>(name: &P, flag: OFlag, mode: Mode) -> Result<RawFd> {
let ret = name.with_nix_path(|cstr| {
#[cfg(any(target_os = "macos", target_os = "ios"))]
unsafe {
libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::c_uint)
}
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
unsafe {
libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::mode_t)
}
})?;
Errno::result(ret)
}
#[cfg(not(target_os = "android"))]
pub fn shm_unlink<P: ?Sized + NixPath>(name: &P) -> Result<()> {
let ret = name.with_nix_path(|cstr| {
unsafe { libc::shm_unlink(cstr.as_ptr()) }
})?;
Errno::result(ret).map(drop)
}