diff options
author | Zach Reizner <zachr@google.com> | 2018-03-28 16:23:43 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-03-29 21:59:44 -0700 |
commit | 3afab33a8d797433b6742963ac34e5cf1a57bf64 (patch) | |
tree | 717125f89fbe2b41d90318ec847d5e779977dffb /sys_util/src/file_flags.rs | |
parent | 29484502829b98f7ac8b8445f75c3d71dd79dbaf (diff) | |
download | crosvm-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.rs | 53 |
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); + } +} |