xref: /aosp_15_r20/external/crosvm/base/src/sys/unix/file_flags.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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