1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
use std::io; use crate::error; use crate::Int; macro_rules! fcntl_raw { ($fd:expr, $cmd:expr$(, $args:expr)*) => { error::convert_ret(libc::fcntl($fd, $cmd$(, $args)*)); }; } #[inline] pub fn dupfd(fd: Int, min_fd: Int) -> io::Result<Int> { unsafe { fcntl_raw!(fd, libc::F_DUPFD, min_fd) } } #[inline] pub fn dupfd_cloexec(fd: Int, min_fd: Int) -> io::Result<Int> { unsafe { fcntl_raw!(fd, libc::F_DUPFD_CLOEXEC, min_fd) } } #[inline] pub fn getflags(fd: Int) -> io::Result<Int> { unsafe { fcntl_raw!(fd, libc::F_GETFD) } } #[inline] pub fn setflags(fd: Int, flags: Int) -> io::Result<()> { unsafe { fcntl_raw!(fd, libc::F_SETFD, flags)? }; Ok(()) } #[inline] pub fn is_inheritable(fd: Int) -> io::Result<bool> { Ok(getflags(fd)? & libc::FD_CLOEXEC == 0) } pub fn set_inheritable(fd: Int, inheritable: bool) -> io::Result<()> { let mut flags = getflags(fd)?; let currently_inheritable = flags & libc::FD_CLOEXEC == 0; if inheritable == currently_inheritable { return Ok(()); } if inheritable { flags &= !(libc::FD_CLOEXEC as Int); } else { flags |= libc::FD_CLOEXEC; } setflags(fd, flags) } #[inline] pub fn set_lock(fd: Int, lock: &libc::flock) -> io::Result<()> { unsafe { fcntl_raw!(fd, libc::F_SETLK, lock)? }; Ok(()) } #[inline] pub fn set_lock_wait(fd: Int, lock: &libc::flock) -> io::Result<()> { unsafe { fcntl_raw!(fd, libc::F_SETLKW, lock)? }; Ok(()) } #[inline] pub fn get_lock(fd: Int, lock: &mut libc::flock) -> io::Result<()> { unsafe { fcntl_raw!(fd, libc::F_GETLK, lock)? }; Ok(()) } #[cfg(test)] mod tests { use std::os::unix::io::AsRawFd; use super::*; #[test] fn test_inheritable() { let f = std::fs::File::open("/dev/null").unwrap(); set_inheritable(f.as_raw_fd(), false).unwrap(); assert!(!is_inheritable(f.as_raw_fd()).unwrap()); set_inheritable(f.as_raw_fd(), false).unwrap(); assert!(!is_inheritable(f.as_raw_fd()).unwrap()); set_inheritable(f.as_raw_fd(), true).unwrap(); assert!(is_inheritable(f.as_raw_fd()).unwrap()); set_inheritable(f.as_raw_fd(), true).unwrap(); assert!(is_inheritable(f.as_raw_fd()).unwrap()); set_inheritable(f.as_raw_fd(), false).unwrap(); assert!(!is_inheritable(f.as_raw_fd()).unwrap()); set_inheritable(f.as_raw_fd(), false).unwrap(); assert!(!is_inheritable(f.as_raw_fd()).unwrap()); } #[test] fn test_dupfd() { let f = std::fs::File::open("/dev/null").unwrap(); let f2 = dupfd(f.as_raw_fd(), 0).unwrap(); assert!(is_inheritable(f2).unwrap()); unsafe { crate::close_fd(f2).unwrap(); } let f2 = dupfd_cloexec(f.as_raw_fd(), 0).unwrap(); assert!(!is_inheritable(f2).unwrap()); unsafe { crate::close_fd(f2).unwrap(); } } }