summary refs log tree commit diff
path: root/sys_util/src/file_flags.rs
diff options
context:
space:
mode:
authorZach Reizner <zachr@google.com>2018-03-28 16:23:43 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-03-29 21:59:44 -0700
commit3afab33a8d797433b6742963ac34e5cf1a57bf64 (patch)
tree717125f89fbe2b41d90318ec847d5e779977dffb /sys_util/src/file_flags.rs
parent29484502829b98f7ac8b8445f75c3d71dd79dbaf (diff)
downloadcrosvm-3afab33a8d797433b6742963ac34e5cf1a57bf64.tar
crosvm-3afab33a8d797433b6742963ac34e5cf1a57bf64.tar.gz
crosvm-3afab33a8d797433b6742963ac34e5cf1a57bf64.tar.bz2
crosvm-3afab33a8d797433b6742963ac34e5cf1a57bf64.tar.lz
crosvm-3afab33a8d797433b6742963ac34e5cf1a57bf64.tar.xz
crosvm-3afab33a8d797433b6742963ac34e5cf1a57bf64.tar.zst
crosvm-3afab33a8d797433b6742963ac34e5cf1a57bf64.zip
sys_util: add type to get open file flags
The only instance of libstd getting file flags is the debug formatter
for `File` which would be hacky to depend on. This change adds a type
and method to directly get open file flags.

TEST=cargo test -p sys_util
BUG=chromium:793688

Change-Id: I9fe411d8cb45d2993e2334ffe41f2eb6ec48de70
Reviewed-on: https://chromium-review.googlesource.com/985615
Commit-Ready: Zach Reizner <zachr@chromium.org>
Tested-by: Zach Reizner <zachr@chromium.org>
Reviewed-by: Stephen Barber <smbarber@chromium.org>
Diffstat (limited to 'sys_util/src/file_flags.rs')
-rw-r--r--sys_util/src/file_flags.rs53
1 files changed, 53 insertions, 0 deletions
diff --git a/sys_util/src/file_flags.rs b/sys_util/src/file_flags.rs
new file mode 100644
index 0000000..c8a3637
--- /dev/null
+++ b/sys_util/src/file_flags.rs
@@ -0,0 +1,53 @@
+// 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, F_GETFL, O_ACCMODE, O_RDONLY, O_WRONLY, O_RDWR, EINVAL};
+
+use {Error, Result, errno_result};
+
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum FileFlags {
+    Read,
+    Write,
+    ReadWrite,
+}
+
+impl FileFlags {
+    pub fn from_file(file: &AsRawFd) -> Result<FileFlags> {
+        // 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 {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);
+    }
+}