base/sys/unix/
file_flags.rs

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
5use libc::fcntl;
6use libc::EINVAL;
7use libc::F_GETFL;
8use libc::O_ACCMODE;
9use libc::O_RDONLY;
10use libc::O_RDWR;
11use libc::O_WRONLY;
12
13use crate::errno_result;
14use crate::AsRawDescriptor;
15use crate::Error;
16use crate::Result;
17
18#[derive(Copy, Clone, Debug, Eq, PartialEq)]
19pub enum FileFlags {
20    Read,
21    Write,
22    ReadWrite,
23}
24
25impl 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)]
45mod tests {
46    use super::*;
47    use crate::sys::pipe;
48    use crate::Event;
49
50    #[test]
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]
58    fn event() {
59        let evt = Event::new().unwrap();
60        assert_eq!(FileFlags::from_file(&evt).unwrap(), FileFlags::ReadWrite);
61    }
62}