use crate::Result;
#[cfg(not(target_os = "android"))]
use crate::NixPath;
use crate::errno::Errno;
#[cfg(not(target_os = "android"))]
#[cfg(feature = "fs")]
use crate::{fcntl::OFlag, sys::stat::Mode};
use libc::{self, c_int, c_void, size_t, off_t};
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"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
PROT_GROWSDOWN;
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
PROT_GROWSUP;
}
}
libc_bitflags!{
pub struct MapFlags: c_int {
MAP_FILE;
MAP_SHARED;
MAP_PRIVATE;
MAP_FIXED;
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_FIXED_NOREPLACE;
#[cfg(target_os = "freebsd")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_EXCL;
MAP_ANON;
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")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_32BIT;
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_GROWSDOWN;
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_DENYWRITE;
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_EXECUTABLE;
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_LOCKED;
#[cfg(not(any(target_os = "dragonfly", target_os = "freebsd")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_NORESERVE;
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_POPULATE;
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_NONBLOCK;
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGETLB;
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_64KB;
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_512KB;
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_1MB;
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_2MB;
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_8MB;
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_16MB;
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_32MB;
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_256MB;
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_512MB;
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_1GB;
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_2GB;
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HUGE_16GB;
#[cfg(target_os = "netbsd")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_WIRED;
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_NOSYNC;
#[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_RENAME;
#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_HASSEMAPHORE;
#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux", target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_STACK;
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_NOCACHE;
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_JIT;
#[cfg(target_os = "freebsd")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_ALIGNED_SUPER;
#[cfg(target_os = "openbsd")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_CONCEAL;
}
}
#[cfg(any(target_os = "linux", target_os = "netbsd"))]
libc_bitflags!{
pub struct MRemapFlags: c_int {
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MREMAP_MAYMOVE;
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MREMAP_FIXED;
#[cfg(target_os = "netbsd")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_FIXED;
#[cfg(target_os = "netbsd")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_REMAPDUP;
}
}
libc_enum!{
#[repr(i32)]
#[non_exhaustive]
pub enum MmapAdvise {
MADV_NORMAL,
MADV_RANDOM,
MADV_SEQUENTIAL,
MADV_WILLNEED,
MADV_DONTNEED,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_REMOVE,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_DONTFORK,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_DOFORK,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_HWPOISON,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_MERGEABLE,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_UNMERGEABLE,
#[cfg(any(target_os = "android",
all(target_os = "linux", any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc",
target_arch = "powerpc64",
target_arch = "s390x",
target_arch = "x86",
target_arch = "x86_64",
target_arch = "sparc64"))))]
MADV_SOFT_OFFLINE,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_HUGEPAGE,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_NOHUGEPAGE,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_DONTDUMP,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_DODUMP,
MADV_FREE,
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_NOSYNC,
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_AUTOSYNC,
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_NOCORE,
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_CORE,
#[cfg(any(target_os = "freebsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_PROTECT,
#[cfg(target_os = "dragonfly")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_INVAL,
#[cfg(target_os = "dragonfly")]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_SETMAP,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_ZERO_WIRED_PAGES,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_FREE_REUSABLE,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_FREE_REUSE,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
#[allow(missing_docs)]
MADV_CAN_REUSE,
}
}
libc_bitflags!{
pub struct MsFlags: c_int {
MS_ASYNC;
MS_INVALIDATE;
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MS_KILLPAGES;
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
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(Errno::last())
} else {
Ok(ret)
}
}
#[cfg(any(target_os = "linux", target_os = "netbsd"))]
pub unsafe fn mremap(
addr: *mut c_void,
old_size: size_t,
new_size: size_t,
flags: MRemapFlags,
new_address: Option<* mut c_void>,
) -> Result<*mut c_void> {
#[cfg(target_os = "linux")]
let ret = libc::mremap(addr, old_size, new_size, flags.bits(), new_address.unwrap_or(std::ptr::null_mut()));
#[cfg(target_os = "netbsd")]
let ret = libc::mremap(
addr,
old_size,
new_address.unwrap_or(std::ptr::null_mut()),
new_size,
flags.bits(),
);
if ret == libc::MAP_FAILED {
Err(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 mprotect(addr: *mut c_void, length: size_t, prot: ProtFlags) -> Result<()> {
Errno::result(libc::mprotect(addr, length, prot.bits())).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"))]
feature! {
#![feature = "fs"]
pub fn shm_open<P>(
name: &P,
flag: OFlag,
mode: Mode
) -> Result<RawFd>
where P: ?Sized + NixPath
{
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)
}