use std::path::Path; use std::io::FilePermission; use libc::{c_int, mode_t}; use errno::{SysResult, SysError}; 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)] #[deriving(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, // not actually here, but brings in line with freebsd 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)] #[deriving(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, // not actually here, but brings in line with freebsd 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: FilePermission) -> SysResult { 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), // FD_FLAGS F_GETFL, F_SETFL(OFlag), // O_NONBLOCK 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) // TODO: Rest of flags } // TODO: Figure out how to handle value fcntl returns 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 } ) }