1 // Copyright 2018 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use libc::fcntl; 6 use libc::EINVAL; 7 use libc::F_GETFL; 8 use libc::O_ACCMODE; 9 use libc::O_RDONLY; 10 use libc::O_RDWR; 11 use libc::O_WRONLY; 12 13 use crate::errno_result; 14 use crate::AsRawDescriptor; 15 use crate::Error; 16 use crate::Result; 17 18 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 19 pub enum FileFlags { 20 Read, 21 Write, 22 ReadWrite, 23 } 24 25 impl FileFlags { from_file(file: &dyn AsRawDescriptor) -> Result<FileFlags>26 pub fn from_file(file: &dyn AsRawDescriptor) -> Result<FileFlags> { 27 // SAFETY: 28 // Trivially safe because fcntl with the F_GETFL command is totally safe and we check for 29 // error. 30 let flags = unsafe { fcntl(file.as_raw_descriptor(), F_GETFL) }; 31 if flags == -1 { 32 errno_result() 33 } else { 34 match flags & O_ACCMODE { 35 O_RDONLY => Ok(FileFlags::Read), 36 O_WRONLY => Ok(FileFlags::Write), 37 O_RDWR => Ok(FileFlags::ReadWrite), 38 _ => Err(Error::new(EINVAL)), 39 } 40 } 41 } 42 } 43 44 #[cfg(test)] 45 mod tests { 46 use super::*; 47 use crate::sys::pipe; 48 use crate::Event; 49 50 #[test] pipe_pair()51 fn pipe_pair() { 52 let (read_pipe, write_pipe) = pipe().unwrap(); 53 assert_eq!(FileFlags::from_file(&read_pipe).unwrap(), FileFlags::Read); 54 assert_eq!(FileFlags::from_file(&write_pipe).unwrap(), FileFlags::Write); 55 } 56 57 #[test] event()58 fn event() { 59 let evt = Event::new().unwrap(); 60 assert_eq!(FileFlags::from_file(&evt).unwrap(), FileFlags::ReadWrite); 61 } 62 } 63