// Copyright 2018 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. use std::os::unix::io::AsRawFd; use libc::{fcntl, EINVAL, F_GETFL, O_ACCMODE, O_RDONLY, O_RDWR, O_WRONLY}; use crate::{errno_result, Error, Result}; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum FileFlags { Read, Write, ReadWrite, } impl FileFlags { pub fn from_file(file: &dyn AsRawFd) -> Result { // Trivially safe because fcntl with the F_GETFL command is totally safe and we check for // error. let flags = unsafe { fcntl(file.as_raw_fd(), F_GETFL) }; if flags == -1 { errno_result() } else { match flags & O_ACCMODE { O_RDONLY => Ok(FileFlags::Read), O_WRONLY => Ok(FileFlags::Write), O_RDWR => Ok(FileFlags::ReadWrite), _ => Err(Error::new(EINVAL)), } } } } #[cfg(test)] mod tests { use super::*; use crate::{pipe, EventFd}; #[test] fn pipe_pair() { let (read_pipe, write_pipe) = pipe(true).unwrap(); assert_eq!(FileFlags::from_file(&read_pipe).unwrap(), FileFlags::Read); assert_eq!(FileFlags::from_file(&write_pipe).unwrap(), FileFlags::Write); } #[test] fn eventfd() { let evt = EventFd::new().unwrap(); assert_eq!(FileFlags::from_file(&evt).unwrap(), FileFlags::ReadWrite); } }