1 // Copyright 2018 The Chromium OS Authors. All rights reserved. 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 std::os::unix::io::AsRawFd; 6 7 use libc::{fcntl, EINVAL, F_GETFL, O_ACCMODE, O_RDONLY, O_RDWR, O_WRONLY}; 8 9 use super::{errno_result, Error, Result}; 10 11 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 12 pub enum FileFlags { 13 Read, 14 Write, 15 ReadWrite, 16 } 17 18 impl FileFlags { from_file(file: &dyn AsRawFd) -> Result<FileFlags>19 pub fn from_file(file: &dyn AsRawFd) -> Result<FileFlags> { 20 // Trivially safe because fcntl with the F_GETFL command is totally safe and we check for 21 // error. 22 let flags = unsafe { fcntl(file.as_raw_fd(), F_GETFL) }; 23 if flags == -1 { 24 errno_result() 25 } else { 26 match flags & O_ACCMODE { 27 O_RDONLY => Ok(FileFlags::Read), 28 O_WRONLY => Ok(FileFlags::Write), 29 O_RDWR => Ok(FileFlags::ReadWrite), 30 _ => Err(Error::new(EINVAL)), 31 } 32 } 33 } 34 } 35 36 #[cfg(test)] 37 mod tests { 38 use super::{ 39 super::{pipe, EventFd}, 40 *, 41 }; 42 43 #[test] pipe_pair()44 fn pipe_pair() { 45 let (read_pipe, write_pipe) = pipe(true).unwrap(); 46 assert_eq!(FileFlags::from_file(&read_pipe).unwrap(), FileFlags::Read); 47 assert_eq!(FileFlags::from_file(&write_pipe).unwrap(), FileFlags::Write); 48 } 49 50 #[test] eventfd()51 fn eventfd() { 52 let evt = EventFd::new().unwrap(); 53 assert_eq!(FileFlags::from_file(&evt).unwrap(), FileFlags::ReadWrite); 54 } 55 } 56