use errno::{SysResult, SysError};
use std::io::FilePermission;
use fcntl::{Fd, OFlag};
use libc::{c_void, size_t, off_t, mode_t};
pub use self::consts::*;
#[cfg(target_os = "linux")]
mod consts {
use libc::c_int;
pub type MmapFlag = c_int;
pub const MAP_SHARED: MmapFlag = 0x00001;
pub const MAP_PRIVATE: MmapFlag = 0x00002;
pub const MAP_FIXED: MmapFlag = 0x00010;
pub const MAP_FILE: MmapFlag = 0x00000;
pub const MAP_ANONYMOUS: MmapFlag = 0x00020;
pub const MAP_ANON: MmapFlag = MAP_ANONYMOUS;
pub const MAP_32BIT: MmapFlag = 0x00040;
pub const MAP_GROWSDOWN: MmapFlag = 0x00100;
pub const MAP_DENYWRITE: MmapFlag = 0x00800;
pub const MAP_EXECUTABLE: MmapFlag = 0x01000;
pub const MAP_LOCKED: MmapFlag = 0x02000;
pub const MAP_NORESERVE: MmapFlag = 0x04000;
pub const MAP_POPULATE: MmapFlag = 0x08000;
pub const MAP_NONBLOCK: MmapFlag = 0x10000;
pub const MAP_STACK: MmapFlag = 0x20000;
pub const MAP_HUGETLB: MmapFlag = 0x40000;
pub type MmapProt = c_int;
pub const PROT_READ: MmapProt = 0x1;
pub const PROT_WRITE: MmapProt = 0x2;
pub const PROT_EXEC: MmapProt = 0x4;
pub const PROT_NONE: MmapProt = 0x0;
pub const PROT_GROWSDOWN: MmapProt = 0x01000000;
pub const PROT_GROWSUP: MmapProt = 0x02000000;
pub const MAP_FAILED: int = -1;
}
#[cfg(target_os = "macos")]
mod consts {
use libc::c_int;
pub type MmapFlag = c_int;
pub const MAP_SHARED: MmapFlag = 0x00001;
pub const MAP_PRIVATE: MmapFlag = 0x00002;
pub const MAP_FIXED: MmapFlag = 0x00010;
pub const MAP_NOCACHE: MmapFlag = 0x00400;
pub const MAP_JIT: MmapFlag = 0x00800;
pub type MmapProt = c_int;
pub const PROT_READ: MmapProt = 0x1;
pub const PROT_WRITE: MmapProt = 0x2;
pub const PROT_EXEC: MmapProt = 0x4;
pub const PROT_NONE: MmapProt = 0x0;
pub const MAP_FAILED: int = -1;
}
mod ffi {
use libc::{c_void, size_t, c_int, c_char, mode_t};
pub use libc::{mmap, munmap};
extern {
pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t) -> c_int;
pub fn shm_unlink(name: *const c_char) -> c_int;
pub fn mlock(addr: *const c_void, len: size_t) -> c_int;
pub fn munlock(addr: *const c_void, len: size_t) -> c_int;
}
}
pub unsafe fn mlock(addr: *const c_void, length: size_t) -> SysResult<()> {
match ffi::mlock(addr, length) {
0 => Ok(()),
_ => Err(SysError::last())
}
}
pub fn munlock(addr: *const c_void, length: size_t) -> SysResult<()> {
match unsafe { ffi::munlock(addr, length) } {
0 => Ok(()),
_ => Err(SysError::last())
}
}
pub fn mmap(addr: *mut c_void, length: size_t, prot: MmapProt, flags: MmapFlag, fd: Fd, offset: off_t) -> SysResult<*mut c_void> {
let ret = unsafe { ffi::mmap(addr, length, prot, flags, fd, offset) };
if ret as int == MAP_FAILED {
Err(SysError::last())
} else {
Ok(ret)
}
}
pub fn munmap(addr: *mut c_void, len: size_t) -> SysResult<()> {
match unsafe { ffi::munmap(addr, len) } {
0 => Ok(()),
_ => Err(SysError::last())
}
}
pub fn shm_open(name: &String, flag: OFlag, mode: FilePermission) -> SysResult<Fd> {
let ret = unsafe { ffi::shm_open(name.to_c_str().as_ptr(), flag.bits(), mode.bits() as mode_t) };
if ret < 0 {
Err(SysError::last())
} else {
Ok(ret)
}
}
pub fn shm_unlink(name: &String) -> SysResult<()> {
let ret = unsafe { ffi::shm_unlink(name.to_c_str().as_ptr()) };
if ret < 0 {
Err(SysError::last())
} else {
Ok(())
}
}