use std::old_path::Path;
use libc::{c_int, mode_t};
use errno::{SysResult, SysError};
use sys::stat::Mode;
use utils::ToCStr;
pub use self::consts::*;
pub use self::ffi::flock;
pub type Fd = c_int;
#[allow(dead_code)]
mod ffi {
pub use libc::{open, fcntl};
pub use self::os::*;
#[cfg(target_os = "linux")]
mod os {
use libc::{c_int, c_short, off_t, pid_t};
#[repr(C)]
#[derive(Copy)]
pub struct flock {
pub l_type: c_short,
pub l_whence: c_short,
pub l_start: off_t,
pub l_len: off_t,
pub l_pid: pid_t,
pub l_sysid: c_int,
}
pub const F_DUPFD: c_int = 0;
pub const F_DUPFD_CLOEXEC: c_int = 1030;
pub const F_GETFD: c_int = 1;
pub const F_SETFD: c_int = 2;
pub const F_GETFL: c_int = 3;
pub const F_SETFL: c_int = 4;
pub const F_SETLK: c_int = 6;
pub const F_SETLKW: c_int = 7;
pub const F_GETLK: c_int = 5;
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
mod os {
use libc::{c_int, c_short, off_t, pid_t};
#[repr(C)]
#[derive(Copy)]
pub struct flock {
pub l_start: off_t,
pub l_len: off_t,
pub l_pid: pid_t,
pub l_type: c_short,
pub l_whence: c_short,
pub l_sysid: c_int,
}
pub const F_DUPFD: c_int = 0;
pub const F_DUPFD_CLOEXEC: c_int = 67;
pub const F_GETFD: c_int = 1;
pub const F_SETFD: c_int = 2;
pub const F_GETFL: c_int = 3;
pub const F_SETFL: c_int = 4;
pub const F_SETLK: c_int = 8;
pub const F_SETLKW: c_int = 9;
pub const F_GETLK: c_int = 7;
}
}
pub fn open(path: &Path, oflag: OFlag, mode: Mode) -> SysResult<Fd> {
let fd = unsafe { ffi::open(path.to_c_str().as_ptr(), oflag.bits(), mode.bits() as mode_t) };
if fd < 0 {
return Err(SysError::last());
}
Ok(fd)
}
pub enum FcntlArg<'a> {
F_DUPFD(Fd),
F_DUPFD_CLOEXEC(Fd),
F_GETFD,
F_SETFD(FdFlag), F_GETFL,
F_SETFL(OFlag), F_SETLK(&'a flock),
F_SETLKW(&'a flock),
F_GETLK(&'a mut flock),
#[cfg(target_os = "linux")]
F_OFD_SETLK(&'a flock),
#[cfg(target_os = "linux")]
F_OFD_SETLKW(&'a flock),
#[cfg(target_os = "linux")]
F_OFD_GETLK(&'a mut flock)
}
pub fn fcntl(fd: Fd, arg: FcntlArg) -> SysResult<()> {
use self::FcntlArg::*;
let res = unsafe {
match arg {
F_SETFD(flag) => ffi::fcntl(fd, ffi::F_SETFD, flag.bits()),
F_SETFL(flag) => ffi::fcntl(fd, ffi::F_SETFL, flag.bits()),
_ => unimplemented!()
}
};
if res < 0 {
return Err(SysError::last());
}
Ok(())
}
#[cfg(target_os = "linux")]
mod consts {
use libc::c_int;
bitflags!(
flags OFlag: c_int {
const O_ACCMODE = 0o00000003,
const O_RDONLY = 0o00000000,
const O_WRONLY = 0o00000001,
const O_RDWR = 0o00000002,
const O_CREAT = 0o00000100,
const O_EXCL = 0o00000200,
const O_NOCTTY = 0o00000400,
const O_TRUNC = 0o00001000,
const O_APPEND = 0o00002000,
const O_NONBLOCK = 0o00004000,
const O_DSYNC = 0o00010000,
const O_DIRECT = 0o00040000,
const O_LARGEFILE = 0o00100000,
const O_DIRECTORY = 0o00200000,
const O_NOFOLLOW = 0o00400000,
const O_NOATIME = 0o01000000,
const O_CLOEXEC = 0o02000000,
const O_SYNC = 0o04000000,
const O_PATH = 0o10000000,
const O_TMPFILE = 0o20000000,
const O_NDELAY = O_NONBLOCK.bits
}
);
bitflags!(
flags FdFlag: c_int {
const FD_CLOEXEC = 1
}
);
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
mod consts {
use libc::c_int;
bitflags!(
flags OFlag: c_int {
const O_ACCMODE = 0x0000003,
const O_RDONLY = 0x0000000,
const O_WRONLY = 0x0000001,
const O_RDWR = 0x0000002,
const O_CREAT = 0x0000200,
const O_EXCL = 0x0000800,
const O_NOCTTY = 0x0020000,
const O_TRUNC = 0x0000400,
const O_APPEND = 0x0000008,
const O_NONBLOCK = 0x0000004,
const O_DSYNC = 0x0400000,
const O_DIRECTORY = 0x0100000,
const O_NOFOLLOW = 0x0000100,
const O_CLOEXEC = 0x1000000,
const O_SYNC = 0x0000080,
const O_NDELAY = O_NONBLOCK.bits,
const O_FSYNC = O_SYNC.bits
}
);
bitflags!(
flags FdFlag: c_int {
const FD_CLOEXEC = 1
}
);
}